// +build linux windows

/*
 *
 * 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.
 *
 */

package alts

import (
	"context"
	"io"
	"os"
	"strings"
	"testing"

	"google.golang.org/grpc/codes"
	altspb "google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp"
	"google.golang.org/grpc/peer"
	"google.golang.org/grpc/status"
)

const (
	testServiceAccount1 = "service_account1"
	testServiceAccount2 = "service_account2"
	testServiceAccount3 = "service_account3"
)

func setupManufacturerReader(testOS string, reader func() (io.Reader, error)) func() {
	tmpOS := runningOS
	tmpReader := manufacturerReader

	// Set test OS and reader function.
	runningOS = testOS
	manufacturerReader = reader
	return func() {
		runningOS = tmpOS
		manufacturerReader = tmpReader
	}

}

func setup(testOS string, testReader io.Reader) func() {
	reader := func() (io.Reader, error) {
		return testReader, nil
	}
	return setupManufacturerReader(testOS, reader)
}

func setupError(testOS string, err error) func() {
	reader := func() (io.Reader, error) {
		return nil, err
	}
	return setupManufacturerReader(testOS, reader)
}

func (s) TestIsRunningOnGCP(t *testing.T) {
	for _, tc := range []struct {
		description string
		testOS      string
		testReader  io.Reader
		out         bool
	}{
		// Linux tests.
		{"linux: not a GCP platform", "linux", strings.NewReader("not GCP"), false},
		{"Linux: GCP platform (Google)", "linux", strings.NewReader("Google"), true},
		{"Linux: GCP platform (Google Compute Engine)", "linux", strings.NewReader("Google Compute Engine"), true},
		{"Linux: GCP platform (Google Compute Engine) with extra spaces", "linux", strings.NewReader("  Google Compute Engine        "), true},
		// Windows tests.
		{"windows: not a GCP platform", "windows", strings.NewReader("not GCP"), false},
		{"windows: GCP platform (Google)", "windows", strings.NewReader("Google"), true},
		{"windows: GCP platform (Google) with extra spaces", "windows", strings.NewReader("  Google     "), true},
	} {
		reverseFunc := setup(tc.testOS, tc.testReader)
		if got, want := isRunningOnGCP(), tc.out; got != want {
			t.Errorf("%v: isRunningOnGCP()=%v, want %v", tc.description, got, want)
		}
		reverseFunc()
	}
}

func (s) TestIsRunningOnGCPNoProductNameFile(t *testing.T) {
	reverseFunc := setupError("linux", os.ErrNotExist)
	if isRunningOnGCP() {
		t.Errorf("ErrNotExist: isRunningOnGCP()=true, want false")
	}
	reverseFunc()
}

func (s) TestAuthInfoFromContext(t *testing.T) {
	ctx := context.Background()
	altsAuthInfo := &fakeALTSAuthInfo{}
	p := &peer.Peer{
		AuthInfo: altsAuthInfo,
	}
	for _, tc := range []struct {
		desc    string
		ctx     context.Context
		success bool
		out     AuthInfo
	}{
		{
			"working case",
			peer.NewContext(ctx, p),
			true,
			altsAuthInfo,
		},
	} {
		authInfo, err := AuthInfoFromContext(tc.ctx)
		if got, want := (err == nil), tc.success; got != want {
			t.Errorf("%v: AuthInfoFromContext(_)=(err=nil)=%v, want %v", tc.desc, got, want)
		}
		if got, want := authInfo, tc.out; got != want {
			t.Errorf("%v:, AuthInfoFromContext(_)=(%v, _), want (%v, _)", tc.desc, got, want)
		}
	}
}

func (s) TestAuthInfoFromPeer(t *testing.T) {
	altsAuthInfo := &fakeALTSAuthInfo{}
	p := &peer.Peer{
		AuthInfo: altsAuthInfo,
	}
	for _, tc := range []struct {
		desc    string
		p       *peer.Peer
		success bool
		out     AuthInfo
	}{
		{
			"working case",
			p,
			true,
			altsAuthInfo,
		},
	} {
		authInfo, err := AuthInfoFromPeer(tc.p)
		if got, want := (err == nil), tc.success; got != want {
			t.Errorf("%v: AuthInfoFromPeer(_)=(err=nil)=%v, want %v", tc.desc, got, want)
		}
		if got, want := authInfo, tc.out; got != want {
			t.Errorf("%v:, AuthInfoFromPeer(_)=(%v, _), want (%v, _)", tc.desc, got, want)
		}
	}
}

func (s) TestClientAuthorizationCheck(t *testing.T) {
	ctx := context.Background()
	altsAuthInfo := &fakeALTSAuthInfo{testServiceAccount1}
	p := &peer.Peer{
		AuthInfo: altsAuthInfo,
	}
	for _, tc := range []struct {
		desc                    string
		ctx                     context.Context
		expectedServiceAccounts []string
		success                 bool
		code                    codes.Code
	}{
		{
			"working case",
			peer.NewContext(ctx, p),
			[]string{testServiceAccount1, testServiceAccount2},
			true,
			codes.OK, // err is nil, code is OK.
		},
		{
			"working case (case ignored)",
			peer.NewContext(ctx, p),
			[]string{strings.ToUpper(testServiceAccount1), testServiceAccount2},
			true,
			codes.OK, // err is nil, code is OK.
		},
		{
			"context does not have AuthInfo",
			ctx,
			[]string{testServiceAccount1, testServiceAccount2},
			false,
			codes.PermissionDenied,
		},
		{
			"unauthorized client",
			peer.NewContext(ctx, p),
			[]string{testServiceAccount2, testServiceAccount3},
			false,
			codes.PermissionDenied,
		},
	} {
		err := ClientAuthorizationCheck(tc.ctx, tc.expectedServiceAccounts)
		if got, want := (err == nil), tc.success; got != want {
			t.Errorf("%v: ClientAuthorizationCheck(_, %v)=(err=nil)=%v, want %v", tc.desc, tc.expectedServiceAccounts, got, want)
		}
		if got, want := status.Code(err), tc.code; got != want {
			t.Errorf("%v: ClientAuthorizationCheck(_, %v).Code=%v, want %v", tc.desc, tc.expectedServiceAccounts, got, want)
		}
	}
}

type fakeALTSAuthInfo struct {
	peerServiceAccount string
}

func (*fakeALTSAuthInfo) AuthType() string            { return "" }
func (*fakeALTSAuthInfo) ApplicationProtocol() string { return "" }
func (*fakeALTSAuthInfo) RecordProtocol() string      { return "" }
func (*fakeALTSAuthInfo) SecurityLevel() altspb.SecurityLevel {
	return altspb.SecurityLevel_SECURITY_NONE
}
func (f *fakeALTSAuthInfo) PeerServiceAccount() string                 { return f.peerServiceAccount }
func (*fakeALTSAuthInfo) LocalServiceAccount() string                  { return "" }
func (*fakeALTSAuthInfo) PeerRPCVersions() *altspb.RpcProtocolVersions { return nil }
