// 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 translate

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"
	translatepb "google.golang.org/genproto/googleapis/cloud/translate/v3"
	longrunningpb "google.golang.org/genproto/googleapis/longrunning"

	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 mockTranslationServer struct {
	// Embed for forward compatibility.
	// Tests will keep working if more methods are added
	// in the future.
	translatepb.TranslationServiceServer

	reqs []proto.Message

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

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

func (s *mockTranslationServer) TranslateText(ctx context.Context, req *translatepb.TranslateTextRequest) (*translatepb.TranslateTextResponse, 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].(*translatepb.TranslateTextResponse), nil
}

func (s *mockTranslationServer) DetectLanguage(ctx context.Context, req *translatepb.DetectLanguageRequest) (*translatepb.DetectLanguageResponse, 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].(*translatepb.DetectLanguageResponse), nil
}

func (s *mockTranslationServer) GetSupportedLanguages(ctx context.Context, req *translatepb.GetSupportedLanguagesRequest) (*translatepb.SupportedLanguages, 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].(*translatepb.SupportedLanguages), nil
}

func (s *mockTranslationServer) BatchTranslateText(ctx context.Context, req *translatepb.BatchTranslateTextRequest) (*longrunningpb.Operation, 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].(*longrunningpb.Operation), nil
}

func (s *mockTranslationServer) CreateGlossary(ctx context.Context, req *translatepb.CreateGlossaryRequest) (*longrunningpb.Operation, 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].(*longrunningpb.Operation), nil
}

func (s *mockTranslationServer) ListGlossaries(ctx context.Context, req *translatepb.ListGlossariesRequest) (*translatepb.ListGlossariesResponse, 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].(*translatepb.ListGlossariesResponse), nil
}

func (s *mockTranslationServer) GetGlossary(ctx context.Context, req *translatepb.GetGlossaryRequest) (*translatepb.Glossary, 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].(*translatepb.Glossary), nil
}

func (s *mockTranslationServer) DeleteGlossary(ctx context.Context, req *translatepb.DeleteGlossaryRequest) (*longrunningpb.Operation, 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].(*longrunningpb.Operation), nil
}

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

var (
	mockTranslation mockTranslationServer
)

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

	serv := grpc.NewServer()
	translatepb.RegisterTranslationServiceServer(serv, &mockTranslation)

	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 TestTranslationServiceTranslateText(t *testing.T) {
	var expectedResponse *translatepb.TranslateTextResponse = &translatepb.TranslateTextResponse{}

	mockTranslation.err = nil
	mockTranslation.reqs = nil

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

	var contents []string = nil
	var targetLanguageCode string = "targetLanguageCode1323228230"
	var formattedParent string = fmt.Sprintf("projects/%s/locations/%s", "[PROJECT]", "[LOCATION]")
	var request = &translatepb.TranslateTextRequest{
		Contents:           contents,
		TargetLanguageCode: targetLanguageCode,
		Parent:             formattedParent,
	}

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

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

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

	if want, got := request, mockTranslation.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 TestTranslationServiceTranslateTextError(t *testing.T) {
	errCode := codes.PermissionDenied
	mockTranslation.err = gstatus.Error(errCode, "test error")

	var contents []string = nil
	var targetLanguageCode string = "targetLanguageCode1323228230"
	var formattedParent string = fmt.Sprintf("projects/%s/locations/%s", "[PROJECT]", "[LOCATION]")
	var request = &translatepb.TranslateTextRequest{
		Contents:           contents,
		TargetLanguageCode: targetLanguageCode,
		Parent:             formattedParent,
	}

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

	resp, err := c.TranslateText(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 TestTranslationServiceDetectLanguage(t *testing.T) {
	var expectedResponse *translatepb.DetectLanguageResponse = &translatepb.DetectLanguageResponse{}

	mockTranslation.err = nil
	mockTranslation.reqs = nil

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

	var formattedParent string = fmt.Sprintf("projects/%s/locations/%s", "[PROJECT]", "[LOCATION]")
	var request = &translatepb.DetectLanguageRequest{
		Parent: formattedParent,
	}

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

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

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

	if want, got := request, mockTranslation.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 TestTranslationServiceDetectLanguageError(t *testing.T) {
	errCode := codes.PermissionDenied
	mockTranslation.err = gstatus.Error(errCode, "test error")

	var formattedParent string = fmt.Sprintf("projects/%s/locations/%s", "[PROJECT]", "[LOCATION]")
	var request = &translatepb.DetectLanguageRequest{
		Parent: formattedParent,
	}

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

	resp, err := c.DetectLanguage(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 TestTranslationServiceGetSupportedLanguages(t *testing.T) {
	var expectedResponse *translatepb.SupportedLanguages = &translatepb.SupportedLanguages{}

	mockTranslation.err = nil
	mockTranslation.reqs = nil

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

	var formattedParent string = fmt.Sprintf("projects/%s/locations/%s", "[PROJECT]", "[LOCATION]")
	var request = &translatepb.GetSupportedLanguagesRequest{
		Parent: formattedParent,
	}

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

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

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

	if want, got := request, mockTranslation.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 TestTranslationServiceGetSupportedLanguagesError(t *testing.T) {
	errCode := codes.PermissionDenied
	mockTranslation.err = gstatus.Error(errCode, "test error")

	var formattedParent string = fmt.Sprintf("projects/%s/locations/%s", "[PROJECT]", "[LOCATION]")
	var request = &translatepb.GetSupportedLanguagesRequest{
		Parent: formattedParent,
	}

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

	resp, err := c.GetSupportedLanguages(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 TestTranslationServiceBatchTranslateText(t *testing.T) {
	var totalCharacters int64 = 1368640955
	var translatedCharacters int64 = 1337326221
	var failedCharacters int64 = 1723028396
	var expectedResponse = &translatepb.BatchTranslateResponse{
		TotalCharacters:      totalCharacters,
		TranslatedCharacters: translatedCharacters,
		FailedCharacters:     failedCharacters,
	}

	mockTranslation.err = nil
	mockTranslation.reqs = nil

	any, err := ptypes.MarshalAny(expectedResponse)
	if err != nil {
		t.Fatal(err)
	}
	mockTranslation.resps = append(mockTranslation.resps[:0], &longrunningpb.Operation{
		Name:   "longrunning-test",
		Done:   true,
		Result: &longrunningpb.Operation_Response{Response: any},
	})

	var formattedParent string = fmt.Sprintf("projects/%s/locations/%s", "[PROJECT]", "[LOCATION]")
	var sourceLanguageCode string = "sourceLanguageCode1687263568"
	var targetLanguageCodes []string = nil
	var inputConfigs []*translatepb.InputConfig = nil
	var outputConfig *translatepb.OutputConfig = &translatepb.OutputConfig{}
	var request = &translatepb.BatchTranslateTextRequest{
		Parent:              formattedParent,
		SourceLanguageCode:  sourceLanguageCode,
		TargetLanguageCodes: targetLanguageCodes,
		InputConfigs:        inputConfigs,
		OutputConfig:        outputConfig,
	}

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

	respLRO, err := c.BatchTranslateText(context.Background(), request)
	if err != nil {
		t.Fatal(err)
	}
	resp, err := respLRO.Wait(context.Background())

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

	if want, got := request, mockTranslation.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 TestTranslationServiceBatchTranslateTextError(t *testing.T) {
	errCode := codes.PermissionDenied
	mockTranslation.err = nil
	mockTranslation.resps = append(mockTranslation.resps[:0], &longrunningpb.Operation{
		Name: "longrunning-test",
		Done: true,
		Result: &longrunningpb.Operation_Error{
			Error: &status.Status{
				Code:    int32(errCode),
				Message: "test error",
			},
		},
	})

	var formattedParent string = fmt.Sprintf("projects/%s/locations/%s", "[PROJECT]", "[LOCATION]")
	var sourceLanguageCode string = "sourceLanguageCode1687263568"
	var targetLanguageCodes []string = nil
	var inputConfigs []*translatepb.InputConfig = nil
	var outputConfig *translatepb.OutputConfig = &translatepb.OutputConfig{}
	var request = &translatepb.BatchTranslateTextRequest{
		Parent:              formattedParent,
		SourceLanguageCode:  sourceLanguageCode,
		TargetLanguageCodes: targetLanguageCodes,
		InputConfigs:        inputConfigs,
		OutputConfig:        outputConfig,
	}

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

	respLRO, err := c.BatchTranslateText(context.Background(), request)
	if err != nil {
		t.Fatal(err)
	}
	resp, err := respLRO.Wait(context.Background())

	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 TestTranslationServiceCreateGlossary(t *testing.T) {
	var name string = "name3373707"
	var entryCount int32 = 811131134
	var expectedResponse = &translatepb.Glossary{
		Name:       name,
		EntryCount: entryCount,
	}

	mockTranslation.err = nil
	mockTranslation.reqs = nil

	any, err := ptypes.MarshalAny(expectedResponse)
	if err != nil {
		t.Fatal(err)
	}
	mockTranslation.resps = append(mockTranslation.resps[:0], &longrunningpb.Operation{
		Name:   "longrunning-test",
		Done:   true,
		Result: &longrunningpb.Operation_Response{Response: any},
	})

	var formattedParent string = fmt.Sprintf("projects/%s/locations/%s", "[PROJECT]", "[LOCATION]")
	var glossary *translatepb.Glossary = &translatepb.Glossary{}
	var request = &translatepb.CreateGlossaryRequest{
		Parent:   formattedParent,
		Glossary: glossary,
	}

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

	respLRO, err := c.CreateGlossary(context.Background(), request)
	if err != nil {
		t.Fatal(err)
	}
	resp, err := respLRO.Wait(context.Background())

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

	if want, got := request, mockTranslation.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 TestTranslationServiceCreateGlossaryError(t *testing.T) {
	errCode := codes.PermissionDenied
	mockTranslation.err = nil
	mockTranslation.resps = append(mockTranslation.resps[:0], &longrunningpb.Operation{
		Name: "longrunning-test",
		Done: true,
		Result: &longrunningpb.Operation_Error{
			Error: &status.Status{
				Code:    int32(errCode),
				Message: "test error",
			},
		},
	})

	var formattedParent string = fmt.Sprintf("projects/%s/locations/%s", "[PROJECT]", "[LOCATION]")
	var glossary *translatepb.Glossary = &translatepb.Glossary{}
	var request = &translatepb.CreateGlossaryRequest{
		Parent:   formattedParent,
		Glossary: glossary,
	}

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

	respLRO, err := c.CreateGlossary(context.Background(), request)
	if err != nil {
		t.Fatal(err)
	}
	resp, err := respLRO.Wait(context.Background())

	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 TestTranslationServiceListGlossaries(t *testing.T) {
	var nextPageToken string = ""
	var glossariesElement *translatepb.Glossary = &translatepb.Glossary{}
	var glossaries = []*translatepb.Glossary{glossariesElement}
	var expectedResponse = &translatepb.ListGlossariesResponse{
		NextPageToken: nextPageToken,
		Glossaries:    glossaries,
	}

	mockTranslation.err = nil
	mockTranslation.reqs = nil

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

	var formattedParent string = fmt.Sprintf("projects/%s/locations/%s", "[PROJECT]", "[LOCATION]")
	var request = &translatepb.ListGlossariesRequest{
		Parent: formattedParent,
	}

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

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

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

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

	want := (interface{})(expectedResponse.Glossaries[0])
	got := (interface{})(resp)
	var ok bool

	switch want := (want).(type) {
	case proto.Message:
		ok = proto.Equal(want, got.(proto.Message))
	default:
		ok = want == got
	}
	if !ok {
		t.Errorf("wrong response %q, want %q)", got, want)
	}
}

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

	var formattedParent string = fmt.Sprintf("projects/%s/locations/%s", "[PROJECT]", "[LOCATION]")
	var request = &translatepb.ListGlossariesRequest{
		Parent: formattedParent,
	}

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

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

	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 TestTranslationServiceGetGlossary(t *testing.T) {
	var name2 string = "name2-1052831874"
	var entryCount int32 = 811131134
	var expectedResponse = &translatepb.Glossary{
		Name:       name2,
		EntryCount: entryCount,
	}

	mockTranslation.err = nil
	mockTranslation.reqs = nil

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

	var formattedName string = fmt.Sprintf("projects/%s/locations/%s/glossaries/%s", "[PROJECT]", "[LOCATION]", "[GLOSSARY]")
	var request = &translatepb.GetGlossaryRequest{
		Name: formattedName,
	}

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

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

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

	if want, got := request, mockTranslation.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 TestTranslationServiceGetGlossaryError(t *testing.T) {
	errCode := codes.PermissionDenied
	mockTranslation.err = gstatus.Error(errCode, "test error")

	var formattedName string = fmt.Sprintf("projects/%s/locations/%s/glossaries/%s", "[PROJECT]", "[LOCATION]", "[GLOSSARY]")
	var request = &translatepb.GetGlossaryRequest{
		Name: formattedName,
	}

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

	resp, err := c.GetGlossary(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 TestTranslationServiceDeleteGlossary(t *testing.T) {
	var name2 string = "name2-1052831874"
	var expectedResponse = &translatepb.DeleteGlossaryResponse{
		Name: name2,
	}

	mockTranslation.err = nil
	mockTranslation.reqs = nil

	any, err := ptypes.MarshalAny(expectedResponse)
	if err != nil {
		t.Fatal(err)
	}
	mockTranslation.resps = append(mockTranslation.resps[:0], &longrunningpb.Operation{
		Name:   "longrunning-test",
		Done:   true,
		Result: &longrunningpb.Operation_Response{Response: any},
	})

	var formattedName string = fmt.Sprintf("projects/%s/locations/%s/glossaries/%s", "[PROJECT]", "[LOCATION]", "[GLOSSARY]")
	var request = &translatepb.DeleteGlossaryRequest{
		Name: formattedName,
	}

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

	respLRO, err := c.DeleteGlossary(context.Background(), request)
	if err != nil {
		t.Fatal(err)
	}
	resp, err := respLRO.Wait(context.Background())

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

	if want, got := request, mockTranslation.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 TestTranslationServiceDeleteGlossaryError(t *testing.T) {
	errCode := codes.PermissionDenied
	mockTranslation.err = nil
	mockTranslation.resps = append(mockTranslation.resps[:0], &longrunningpb.Operation{
		Name: "longrunning-test",
		Done: true,
		Result: &longrunningpb.Operation_Error{
			Error: &status.Status{
				Code:    int32(errCode),
				Message: "test error",
			},
		},
	})

	var formattedName string = fmt.Sprintf("projects/%s/locations/%s/glossaries/%s", "[PROJECT]", "[LOCATION]", "[GLOSSARY]")
	var request = &translatepb.DeleteGlossaryRequest{
		Name: formattedName,
	}

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

	respLRO, err := c.DeleteGlossary(context.Background(), request)
	if err != nil {
		t.Fatal(err)
	}
	resp, err := respLRO.Wait(context.Background())

	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
}
