// +build go1.10,linux,!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 test

import (
	"testing"
	"time"

	"google.golang.org/grpc/internal/channelz"
	testpb "google.golang.org/grpc/test/grpc_testing"
)

func (s) TestCZSocketMetricsSocketOption(t *testing.T) {
	envs := []env{tcpClearRREnv, tcpTLSRREnv}
	for _, e := range envs {
		testCZSocketMetricsSocketOption(t, e)
	}
}

func testCZSocketMetricsSocketOption(t *testing.T, e env) {
	czCleanup := channelz.NewChannelzStorage()
	defer czCleanupWrapper(czCleanup, t)
	te := newTest(t, e)
	te.startServer(&testServer{security: e.security})
	defer te.tearDown()
	cc := te.clientConn()
	tc := testpb.NewTestServiceClient(cc)
	doSuccessfulUnaryCall(tc, t)

	time.Sleep(10 * time.Millisecond)
	ss, _ := channelz.GetServers(0, 0)
	if len(ss) != 1 {
		t.Fatalf("There should be one server, not %d", len(ss))
	}
	if len(ss[0].ListenSockets) != 1 {
		t.Fatalf("There should be one listen socket, not %d", len(ss[0].ListenSockets))
	}
	for id := range ss[0].ListenSockets {
		sm := channelz.GetSocket(id)
		if sm == nil || sm.SocketData == nil || sm.SocketData.SocketOptions == nil {
			t.Fatalf("Unable to get server listen socket options")
		}
	}
	ns, _ := channelz.GetServerSockets(ss[0].ID, 0, 0)
	if len(ns) != 1 {
		t.Fatalf("There should be one server normal socket, not %d", len(ns))
	}
	if ns[0] == nil || ns[0].SocketData == nil || ns[0].SocketData.SocketOptions == nil {
		t.Fatalf("Unable to get server normal socket options")
	}

	tchan, _ := channelz.GetTopChannels(0, 0)
	if len(tchan) != 1 {
		t.Fatalf("There should only be one top channel, not %d", len(tchan))
	}
	if len(tchan[0].SubChans) != 1 {
		t.Fatalf("There should only be one subchannel under top channel %d, not %d", tchan[0].ID, len(tchan[0].SubChans))
	}
	var id int64
	for id = range tchan[0].SubChans {
		break
	}
	sc := channelz.GetSubChannel(id)
	if sc == nil {
		t.Fatalf("There should only be one socket under subchannel %d, not 0", id)
	}
	if len(sc.Sockets) != 1 {
		t.Fatalf("There should only be one socket under subchannel %d, not %d", sc.ID, len(sc.Sockets))
	}
	for id = range sc.Sockets {
		break
	}
	skt := channelz.GetSocket(id)
	if skt == nil || skt.SocketData == nil || skt.SocketData.SocketOptions == nil {
		t.Fatalf("Unable to get client normal socket options")
	}
}
