// Copyright 2023 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//go:build !build_with_native_toolchain

package netstack

import (
	"context"
	"sync"
	"syscall/zx"
	"testing"

	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/routes"
	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/routetypes"
	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/util"

	fnetRoutes "fidl/fuchsia/net/routes"

	"gvisor.dev/gvisor/pkg/tcpip"
)

type watcherHolder struct {
	version routetypes.IpProtoTag
	v4      *fnetRoutes.WatcherV4WithCtxInterface
	v6      *fnetRoutes.WatcherV6WithCtxInterface
}

func (w watcherHolder) expectPeerClosed(ctx context.Context, t *testing.T) {
	var err error
	switch w.version {
	case routetypes.IPv4:
		_, err = w.v4.Watch(ctx)
	case routetypes.IPv6:
		_, err = w.v6.Watch(ctx)
	default:
		t.Fatalf("unsupported IP protocol version: %d", w.version)
	}

	if err == nil {
		t.Errorf("call to Watch unexpectedly succeeded.")
	} else if zxErr, ok := err.(*zx.Error); !ok || zxErr.Status != zx.ErrPeerClosed {
		t.Errorf("got err=%s, want=zx.ErrPeerClosed", err)
	}
}

// TestRoutesWatcherMetrics verifies that fidlRoutesWatcherMetrics properly
// track Watcher creation & deletion.
func TestRoutesWatcherMetrics(t *testing.T) {
	// Instantiate Watcher clients.
	watcher_v4_req, watcher_v4, err := fnetRoutes.NewWatcherV4WithCtxInterfaceRequest()
	if err != nil {
		t.Fatalf("failed to instantiate WatcherV4 Client")
	}
	watcher_v6_req, watcher_v6, err := fnetRoutes.NewWatcherV6WithCtxInterfaceRequest()
	if err != nil {
		t.Fatalf("failed to instantiate WatcherV6 Client")
	}

	// Instantiate the routesWatcherEventLoop.
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	interruptsChan := make(chan routeInterrupt, maxPendingInterrupts)
	metrics := fidlRoutesWatcherMetrics{}
	var wg sync.WaitGroup
	go func() {
		wg.Add(1)
		routesWatcherEventLoop(ctx, interruptsChan, &metrics)
		wg.Done()
	}()

	// Connect the Watcher clients, using Watch as a means to synchronize and
	// wait for the watcher to be installed.
	interruptsChan <- &getWatcherV4Request{
		req:     watcher_v4_req,
		options: fnetRoutes.WatcherOptionsV4{},
	}
	if _, err = watcher_v4.Watch(ctx); err != nil {
		t.Errorf("failed to Watch: %s", err)
	}
	if got := metrics.count_v4.Load(); got != 1 {
		t.Errorf("got %d WatcherV4 client; expected 1", got)
	}
	if got := metrics.count_v6.Load(); got != 0 {
		t.Errorf("got %d WatcherV6 client; expected 0", got)
	}
	interruptsChan <- &getWatcherV6Request{
		req:     watcher_v6_req,
		options: fnetRoutes.WatcherOptionsV6{},
	}
	if _, err = watcher_v6.Watch(ctx); err != nil {
		t.Errorf("failed to Watch: %s", err)
	}
	if got := metrics.count_v4.Load(); got != 1 {
		t.Errorf("got %d WatcherV4 client; expected 1", got)
	}
	if got := metrics.count_v6.Load(); got != 1 {
		t.Errorf("got %d WatcherV6 client; expected 1", got)
	}

	// Abort the backing implementations
	cancel()

	wg.Wait()
	if got := metrics.count_v4.Load(); got != 0 {
		t.Errorf("got %d WatcherV4 client; expected 0", got)
	}
	if got := metrics.count_v6.Load(); got != 0 {
		t.Errorf("got %d WatcherV6 client; expected 0", got)
	}
}

// TestRoutesWatcherSlowClient verifies that clients who consume events slower
// than they're produced eventually get terminated.
func TestRoutesWatcherSlowClient(t *testing.T) {
	// Instantiate Watcher clients.
	watcher_v4_req, watcher_v4, err := fnetRoutes.NewWatcherV4WithCtxInterfaceRequest()
	if err != nil {
		t.Fatalf("failed to instantiate WatcherV4 Client")
	}
	watcher_v6_req, watcher_v6, err := fnetRoutes.NewWatcherV6WithCtxInterfaceRequest()
	if err != nil {
		t.Fatalf("failed to instantiate WatcherV6 Client")
	}

	tests := []struct {
		name        string
		subnet      tcpip.Address
		subnet_mask tcpip.AddressMask
		req         routesGetWatcherRequest
		watcher     watcherHolder
	}{
		{
			name:        "IPv4",
			subnet:      util.Parse("192.168.0.0"),
			subnet_mask: util.ParseMask("255.255.255.0"),
			req: &getWatcherV4Request{
				req:     watcher_v4_req,
				options: fnetRoutes.WatcherOptionsV4{},
			},
			watcher: watcherHolder{
				version: routetypes.IPv4,
				v4:      watcher_v4,
			},
		},
		{
			name:        "IPv6",
			subnet:      util.Parse("fe80::"),
			subnet_mask: util.ParseMask("ffff:ffff:ffff:ffff::"),
			req: &getWatcherV6Request{
				req:     watcher_v6_req,
				options: fnetRoutes.WatcherOptionsV6{},
			},
			watcher: watcherHolder{
				version: routetypes.IPv6,
				v6:      watcher_v6,
			},
		},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			// Instantiate the routesWatcherEventLoop.
			ctx, cancel := context.WithCancel(context.Background())
			defer cancel()
			// Note; don't buffer maxPendingInterrupts; buffering would break the
			// synchronization of the test and make it flaky.
			interruptChan := make(chan routeInterrupt, 1)
			metrics := fidlRoutesWatcherMetrics{}
			go routesWatcherEventLoop(ctx, interruptChan, &metrics)

			// Connect the Watcher client.
			switch req := test.req.(type) {
			case *getWatcherV4Request:
				interruptChan <- req
			case *getWatcherV6Request:
				interruptChan <- req
			}

			// Add and remove a route to generate events.
			subnet, err := tcpip.NewSubnet(test.subnet, test.subnet_mask)
			if err != nil {
				t.Fatalf("failed to create subnet: %s", err)
			}
			route := routetypes.ExtendedRoute{
				Route: tcpip.Route{
					Destination: subnet,
				},
			}
			for i := 0; i <= int(maxPendingEventsPerClient)+1; i++ {
				change := routes.RoutingTableChange{
					Route: route,
				}
				if i%2 == 0 {
					change.Change = routetypes.RouteAdded
				} else {
					change.Change = routetypes.RouteRemoved
				}
				interruptChan <- &routingTableChange{change}
			}

			// Observe PEER_CLOSED on the watcher.
			test.watcher.expectPeerClosed(ctx, t)
		})
	}
}
