// +build linux,go1.10,!appengine

/*
 *
 * Copyright 2018 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

// The test in this file should be run in an environment that has go1.10 or later,
// as the function SyscallConn() (required to get socket option) was introduced
// to net.TCPListener in go1.10.

package channelz_test

import (
	"net"
	"reflect"
	"syscall"
	"testing"

	"golang.org/x/sys/unix"
	"google.golang.org/grpc/internal/channelz"
)

func TestGetSocketOpt(t *testing.T) {
	network, addr := "tcp", ":0"
	ln, err := net.Listen(network, addr)
	if err != nil {
		t.Fatalf("net.Listen(%s,%s) failed with err: %v", network, addr, err)
	}
	defer ln.Close()
	go func() {
		ln.Accept()
	}()
	conn, _ := net.Dial(network, ln.Addr().String())
	defer conn.Close()
	tcpc := conn.(*net.TCPConn)
	raw, err := tcpc.SyscallConn()
	if err != nil {
		t.Fatalf("SyscallConn() failed due to %v", err)
	}

	l := &unix.Linger{Onoff: 1, Linger: 5}
	recvTimout := &unix.Timeval{Sec: 100}
	sendTimeout := &unix.Timeval{Sec: 8888}
	raw.Control(func(fd uintptr) {
		err := unix.SetsockoptLinger(int(fd), syscall.SOL_SOCKET, syscall.SO_LINGER, l)
		if err != nil {
			t.Fatalf("failed to SetsockoptLinger(%v,%v,%v,%v) due to %v", int(fd), syscall.SOL_SOCKET, syscall.SO_LINGER, l, err)
		}
		err = unix.SetsockoptTimeval(int(fd), syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, recvTimout)
		if err != nil {
			t.Fatalf("failed to SetsockoptTimeval(%v,%v,%v,%v) due to %v", int(fd), syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, recvTimout, err)
		}
		err = unix.SetsockoptTimeval(int(fd), syscall.SOL_SOCKET, syscall.SO_SNDTIMEO, sendTimeout)
		if err != nil {
			t.Fatalf("failed to SetsockoptTimeval(%v,%v,%v,%v) due to %v", int(fd), syscall.SOL_SOCKET, syscall.SO_SNDTIMEO, sendTimeout, err)
		}
	})
	sktopt := channelz.GetSocketOption(conn)
	if !reflect.DeepEqual(sktopt.Linger, l) {
		t.Fatalf("get socket option linger, want: %v, got %v", l, sktopt.Linger)
	}
	if !reflect.DeepEqual(sktopt.RecvTimeout, recvTimout) {
		t.Logf("get socket option recv timeout, want: %v, got %v, may be caused by system allowing non or partial setting of this value", recvTimout, sktopt.RecvTimeout)
	}
	if !reflect.DeepEqual(sktopt.SendTimeout, sendTimeout) {
		t.Logf("get socket option send timeout, want: %v, got %v, may be caused by system allowing non or partial setting of this value", sendTimeout, sktopt.SendTimeout)
	}
	if sktopt == nil || sktopt.TCPInfo != nil && sktopt.TCPInfo.State != 1 {
		t.Fatalf("TCPInfo.State want 1 (TCP_ESTABLISHED), got %v", sktopt)
	}

	sktopt = channelz.GetSocketOption(ln)
	if sktopt == nil || sktopt.TCPInfo == nil || sktopt.TCPInfo.State != 10 {
		t.Fatalf("TCPInfo.State want 10 (TCP_LISTEN), got %v", sktopt)
	}
}
