// Copyright 2019 Google LLC
//
// 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
//
//     https://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.

// Code generated by gapic-generator. DO NOT EDIT.

package texttospeech

import (
	"context"
	"flag"
	"fmt"
	"io"
	"log"
	"net"
	"os"
	"strings"
	"testing"

	"github.com/golang/protobuf/proto"
	"github.com/golang/protobuf/ptypes"
	"google.golang.org/api/option"
	texttospeechpb "google.golang.org/genproto/googleapis/cloud/texttospeech/v1"

	status "google.golang.org/genproto/googleapis/rpc/status"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/metadata"

	gstatus "google.golang.org/grpc/status"
)

var _ = io.EOF
var _ = ptypes.MarshalAny
var _ status.Status

type mockTextToSpeechServer struct {
	// Embed for forward compatibility.
	// Tests will keep working if more methods are added
	// in the future.
	texttospeechpb.TextToSpeechServer

	reqs []proto.Message

	// If set, all calls return this error.
	err error

	// responses to return if err == nil
	resps []proto.Message
}

func (s *mockTextToSpeechServer) ListVoices(ctx context.Context, req *texttospeechpb.ListVoicesRequest) (*texttospeechpb.ListVoicesResponse, error) {
	md, _ := metadata.FromIncomingContext(ctx)
	if xg := md["x-goog-api-client"]; len(xg) == 0 || !strings.Contains(xg[0], "gl-go/") {
		return nil, fmt.Errorf("x-goog-api-client = %v, expected gl-go key", xg)
	}
	s.reqs = append(s.reqs, req)
	if s.err != nil {
		return nil, s.err
	}
	return s.resps[0].(*texttospeechpb.ListVoicesResponse), nil
}

func (s *mockTextToSpeechServer) SynthesizeSpeech(ctx context.Context, req *texttospeechpb.SynthesizeSpeechRequest) (*texttospeechpb.SynthesizeSpeechResponse, error) {
	md, _ := metadata.FromIncomingContext(ctx)
	if xg := md["x-goog-api-client"]; len(xg) == 0 || !strings.Contains(xg[0], "gl-go/") {
		return nil, fmt.Errorf("x-goog-api-client = %v, expected gl-go key", xg)
	}
	s.reqs = append(s.reqs, req)
	if s.err != nil {
		return nil, s.err
	}
	return s.resps[0].(*texttospeechpb.SynthesizeSpeechResponse), nil
}

// clientOpt is the option tests should use to connect to the test server.
// It is initialized by TestMain.
var clientOpt option.ClientOption

var (
	mockTextToSpeech mockTextToSpeechServer
)

func TestMain(m *testing.M) {
	flag.Parse()

	serv := grpc.NewServer()
	texttospeechpb.RegisterTextToSpeechServer(serv, &mockTextToSpeech)

	lis, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		log.Fatal(err)
	}
	go serv.Serve(lis)

	conn, err := grpc.Dial(lis.Addr().String(), grpc.WithInsecure())
	if err != nil {
		log.Fatal(err)
	}
	clientOpt = option.WithGRPCConn(conn)

	os.Exit(m.Run())
}

func TestTextToSpeechListVoices(t *testing.T) {
	var expectedResponse *texttospeechpb.ListVoicesResponse = &texttospeechpb.ListVoicesResponse{}

	mockTextToSpeech.err = nil
	mockTextToSpeech.reqs = nil

	mockTextToSpeech.resps = append(mockTextToSpeech.resps[:0], expectedResponse)

	var request *texttospeechpb.ListVoicesRequest = &texttospeechpb.ListVoicesRequest{}

	c, err := NewClient(context.Background(), clientOpt)
	if err != nil {
		t.Fatal(err)
	}

	resp, err := c.ListVoices(context.Background(), request)

	if err != nil {
		t.Fatal(err)
	}

	if want, got := request, mockTextToSpeech.reqs[0]; !proto.Equal(want, got) {
		t.Errorf("wrong request %q, want %q", got, want)
	}

	if want, got := expectedResponse, resp; !proto.Equal(want, got) {
		t.Errorf("wrong response %q, want %q)", got, want)
	}
}

func TestTextToSpeechListVoicesError(t *testing.T) {
	errCode := codes.PermissionDenied
	mockTextToSpeech.err = gstatus.Error(errCode, "test error")

	var request *texttospeechpb.ListVoicesRequest = &texttospeechpb.ListVoicesRequest{}

	c, err := NewClient(context.Background(), clientOpt)
	if err != nil {
		t.Fatal(err)
	}

	resp, err := c.ListVoices(context.Background(), request)

	if st, ok := gstatus.FromError(err); !ok {
		t.Errorf("got error %v, expected grpc error", err)
	} else if c := st.Code(); c != errCode {
		t.Errorf("got error code %q, want %q", c, errCode)
	}
	_ = resp
}
func TestTextToSpeechSynthesizeSpeech(t *testing.T) {
	var audioContent []byte = []byte("16")
	var expectedResponse = &texttospeechpb.SynthesizeSpeechResponse{
		AudioContent: audioContent,
	}

	mockTextToSpeech.err = nil
	mockTextToSpeech.reqs = nil

	mockTextToSpeech.resps = append(mockTextToSpeech.resps[:0], expectedResponse)

	var input *texttospeechpb.SynthesisInput = &texttospeechpb.SynthesisInput{}
	var voice *texttospeechpb.VoiceSelectionParams = &texttospeechpb.VoiceSelectionParams{}
	var audioConfig *texttospeechpb.AudioConfig = &texttospeechpb.AudioConfig{}
	var request = &texttospeechpb.SynthesizeSpeechRequest{
		Input:       input,
		Voice:       voice,
		AudioConfig: audioConfig,
	}

	c, err := NewClient(context.Background(), clientOpt)
	if err != nil {
		t.Fatal(err)
	}

	resp, err := c.SynthesizeSpeech(context.Background(), request)

	if err != nil {
		t.Fatal(err)
	}

	if want, got := request, mockTextToSpeech.reqs[0]; !proto.Equal(want, got) {
		t.Errorf("wrong request %q, want %q", got, want)
	}

	if want, got := expectedResponse, resp; !proto.Equal(want, got) {
		t.Errorf("wrong response %q, want %q)", got, want)
	}
}

func TestTextToSpeechSynthesizeSpeechError(t *testing.T) {
	errCode := codes.PermissionDenied
	mockTextToSpeech.err = gstatus.Error(errCode, "test error")

	var input *texttospeechpb.SynthesisInput = &texttospeechpb.SynthesisInput{}
	var voice *texttospeechpb.VoiceSelectionParams = &texttospeechpb.VoiceSelectionParams{}
	var audioConfig *texttospeechpb.AudioConfig = &texttospeechpb.AudioConfig{}
	var request = &texttospeechpb.SynthesizeSpeechRequest{
		Input:       input,
		Voice:       voice,
		AudioConfig: audioConfig,
	}

	c, err := NewClient(context.Background(), clientOpt)
	if err != nil {
		t.Fatal(err)
	}

	resp, err := c.SynthesizeSpeech(context.Background(), request)

	if st, ok := gstatus.FromError(err); !ok {
		t.Errorf("got error %v, expected grpc error", err)
	} else if c := st.Code(); c != errCode {
		t.Errorf("got error code %q, want %q", c, errCode)
	}
	_ = resp
}
