// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause

//go:build linux

package routetable

import (
	"fmt"
	"net/netip"
	"testing"

	"golang.org/x/sys/unix"
)

func TestGetRouteTable(t *testing.T) {
	routes, err := Get(512000) // arbitrarily large
	if err != nil {
		t.Fatal(err)
	}

	// Basic assertion: we have at least one 'default' route in the main table
	var (
		hasDefault bool
	)
	for _, route := range routes {
		if route.Dst == defaultRouteIPv4 && route.Sys.(RouteEntryLinux).Table == unix.RT_TABLE_MAIN {
			hasDefault = true
		}
	}
	if !hasDefault {
		t.Errorf("expected at least one default route; routes=%v", routes)
	}
}

func TestRouteEntryFormatting(t *testing.T) {
	testCases := []struct {
		re   RouteEntry
		want string
	}{
		{
			re: RouteEntry{
				Family:    4,
				Type:      RouteTypeMulticast,
				Dst:       RouteDestination{Prefix: netip.MustParsePrefix("100.64.0.0/10")},
				Gateway:   netip.MustParseAddr("1.2.3.1"),
				Interface: "tailscale0",
				Sys: RouteEntryLinux{
					Type:     unix.RTN_UNICAST,
					Table:    52,
					Proto:    unix.RTPROT_STATIC,
					Src:      netip.MustParseAddr("1.2.3.4"),
					Priority: 555,
				},
			},
			want: `{Family: IPv4, Type: multicast, Dst: 100.64.0.0/10, Gateway: 1.2.3.1, Interface: tailscale0, Sys: {Type: unicast, Table: 52, Proto: static, Src: 1.2.3.4, Priority: 555}}`,
		},
		{
			re: RouteEntry{
				Family:  4,
				Type:    RouteTypeUnicast,
				Dst:     RouteDestination{Prefix: netip.MustParsePrefix("1.2.3.0/24")},
				Gateway: netip.MustParseAddr("1.2.3.1"),
				Sys: RouteEntryLinux{
					Type:  unix.RTN_UNICAST,
					Table: unix.RT_TABLE_MAIN,
					Proto: unix.RTPROT_BOOT,
				},
			},
			want: `{Family: IPv4, Dst: 1.2.3.0/24, Gateway: 1.2.3.1, Sys: {Type: unicast}}`,
		},
	}
	for _, tc := range testCases {
		t.Run("", func(t *testing.T) {
			got := fmt.Sprint(tc.re)
			if got != tc.want {
				t.Fatalf("RouteEntry.String() = %q; want %q", got, tc.want)
			}
		})
	}
}
