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

import (
	emptypb "github.com/golang/protobuf/ptypes/empty"
	iotpb "google.golang.org/genproto/googleapis/cloud/iot/v1"
	iampb "google.golang.org/genproto/googleapis/iam/v1"
	field_maskpb "google.golang.org/genproto/protobuf/field_mask"
)

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

	reqs []proto.Message

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

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

func (s *mockDeviceManagerServer) CreateDeviceRegistry(ctx context.Context, req *iotpb.CreateDeviceRegistryRequest) (*iotpb.DeviceRegistry, 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].(*iotpb.DeviceRegistry), nil
}

func (s *mockDeviceManagerServer) GetDeviceRegistry(ctx context.Context, req *iotpb.GetDeviceRegistryRequest) (*iotpb.DeviceRegistry, 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].(*iotpb.DeviceRegistry), nil
}

func (s *mockDeviceManagerServer) UpdateDeviceRegistry(ctx context.Context, req *iotpb.UpdateDeviceRegistryRequest) (*iotpb.DeviceRegistry, 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].(*iotpb.DeviceRegistry), nil
}

func (s *mockDeviceManagerServer) DeleteDeviceRegistry(ctx context.Context, req *iotpb.DeleteDeviceRegistryRequest) (*emptypb.Empty, 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].(*emptypb.Empty), nil
}

func (s *mockDeviceManagerServer) ListDeviceRegistries(ctx context.Context, req *iotpb.ListDeviceRegistriesRequest) (*iotpb.ListDeviceRegistriesResponse, 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].(*iotpb.ListDeviceRegistriesResponse), nil
}

func (s *mockDeviceManagerServer) CreateDevice(ctx context.Context, req *iotpb.CreateDeviceRequest) (*iotpb.Device, 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].(*iotpb.Device), nil
}

func (s *mockDeviceManagerServer) GetDevice(ctx context.Context, req *iotpb.GetDeviceRequest) (*iotpb.Device, 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].(*iotpb.Device), nil
}

func (s *mockDeviceManagerServer) UpdateDevice(ctx context.Context, req *iotpb.UpdateDeviceRequest) (*iotpb.Device, 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].(*iotpb.Device), nil
}

func (s *mockDeviceManagerServer) DeleteDevice(ctx context.Context, req *iotpb.DeleteDeviceRequest) (*emptypb.Empty, 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].(*emptypb.Empty), nil
}

func (s *mockDeviceManagerServer) ListDevices(ctx context.Context, req *iotpb.ListDevicesRequest) (*iotpb.ListDevicesResponse, 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].(*iotpb.ListDevicesResponse), nil
}

func (s *mockDeviceManagerServer) ModifyCloudToDeviceConfig(ctx context.Context, req *iotpb.ModifyCloudToDeviceConfigRequest) (*iotpb.DeviceConfig, 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].(*iotpb.DeviceConfig), nil
}

func (s *mockDeviceManagerServer) ListDeviceConfigVersions(ctx context.Context, req *iotpb.ListDeviceConfigVersionsRequest) (*iotpb.ListDeviceConfigVersionsResponse, 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].(*iotpb.ListDeviceConfigVersionsResponse), nil
}

func (s *mockDeviceManagerServer) ListDeviceStates(ctx context.Context, req *iotpb.ListDeviceStatesRequest) (*iotpb.ListDeviceStatesResponse, 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].(*iotpb.ListDeviceStatesResponse), nil
}

func (s *mockDeviceManagerServer) SetIamPolicy(ctx context.Context, req *iampb.SetIamPolicyRequest) (*iampb.Policy, 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].(*iampb.Policy), nil
}

func (s *mockDeviceManagerServer) GetIamPolicy(ctx context.Context, req *iampb.GetIamPolicyRequest) (*iampb.Policy, 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].(*iampb.Policy), nil
}

func (s *mockDeviceManagerServer) TestIamPermissions(ctx context.Context, req *iampb.TestIamPermissionsRequest) (*iampb.TestIamPermissionsResponse, 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].(*iampb.TestIamPermissionsResponse), nil
}

func (s *mockDeviceManagerServer) SendCommandToDevice(ctx context.Context, req *iotpb.SendCommandToDeviceRequest) (*iotpb.SendCommandToDeviceResponse, 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].(*iotpb.SendCommandToDeviceResponse), nil
}

func (s *mockDeviceManagerServer) BindDeviceToGateway(ctx context.Context, req *iotpb.BindDeviceToGatewayRequest) (*iotpb.BindDeviceToGatewayResponse, 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].(*iotpb.BindDeviceToGatewayResponse), nil
}

func (s *mockDeviceManagerServer) UnbindDeviceFromGateway(ctx context.Context, req *iotpb.UnbindDeviceFromGatewayRequest) (*iotpb.UnbindDeviceFromGatewayResponse, 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].(*iotpb.UnbindDeviceFromGatewayResponse), nil
}

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

var (
	mockDeviceManager mockDeviceManagerServer
)

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

	serv := grpc.NewServer()
	iotpb.RegisterDeviceManagerServer(serv, &mockDeviceManager)

	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 TestDeviceManagerCreateDeviceRegistry(t *testing.T) {
	var id string = "id3355"
	var name string = "name3373707"
	var expectedResponse = &iotpb.DeviceRegistry{
		Id:   id,
		Name: name,
	}

	mockDeviceManager.err = nil
	mockDeviceManager.reqs = nil

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

	var formattedParent string = fmt.Sprintf("projects/%s/locations/%s", "[PROJECT]", "[LOCATION]")
	var deviceRegistry *iotpb.DeviceRegistry = &iotpb.DeviceRegistry{}
	var request = &iotpb.CreateDeviceRegistryRequest{
		Parent:         formattedParent,
		DeviceRegistry: deviceRegistry,
	}

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

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

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

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

	var formattedParent string = fmt.Sprintf("projects/%s/locations/%s", "[PROJECT]", "[LOCATION]")
	var deviceRegistry *iotpb.DeviceRegistry = &iotpb.DeviceRegistry{}
	var request = &iotpb.CreateDeviceRegistryRequest{
		Parent:         formattedParent,
		DeviceRegistry: deviceRegistry,
	}

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

	resp, err := c.CreateDeviceRegistry(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 TestDeviceManagerGetDeviceRegistry(t *testing.T) {
	var id string = "id3355"
	var name2 string = "name2-1052831874"
	var expectedResponse = &iotpb.DeviceRegistry{
		Id:   id,
		Name: name2,
	}

	mockDeviceManager.err = nil
	mockDeviceManager.reqs = nil

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

	var formattedName string = fmt.Sprintf("projects/%s/locations/%s/registries/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]")
	var request = &iotpb.GetDeviceRegistryRequest{
		Name: formattedName,
	}

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

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

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

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

	var formattedName string = fmt.Sprintf("projects/%s/locations/%s/registries/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]")
	var request = &iotpb.GetDeviceRegistryRequest{
		Name: formattedName,
	}

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

	resp, err := c.GetDeviceRegistry(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 TestDeviceManagerUpdateDeviceRegistry(t *testing.T) {
	var id string = "id3355"
	var name string = "name3373707"
	var expectedResponse = &iotpb.DeviceRegistry{
		Id:   id,
		Name: name,
	}

	mockDeviceManager.err = nil
	mockDeviceManager.reqs = nil

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

	var deviceRegistry *iotpb.DeviceRegistry = &iotpb.DeviceRegistry{}
	var updateMask *field_maskpb.FieldMask = &field_maskpb.FieldMask{}
	var request = &iotpb.UpdateDeviceRegistryRequest{
		DeviceRegistry: deviceRegistry,
		UpdateMask:     updateMask,
	}

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

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

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

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

	var deviceRegistry *iotpb.DeviceRegistry = &iotpb.DeviceRegistry{}
	var updateMask *field_maskpb.FieldMask = &field_maskpb.FieldMask{}
	var request = &iotpb.UpdateDeviceRegistryRequest{
		DeviceRegistry: deviceRegistry,
		UpdateMask:     updateMask,
	}

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

	resp, err := c.UpdateDeviceRegistry(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 TestDeviceManagerDeleteDeviceRegistry(t *testing.T) {
	var expectedResponse *emptypb.Empty = &emptypb.Empty{}

	mockDeviceManager.err = nil
	mockDeviceManager.reqs = nil

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

	var formattedName string = fmt.Sprintf("projects/%s/locations/%s/registries/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]")
	var request = &iotpb.DeleteDeviceRegistryRequest{
		Name: formattedName,
	}

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

	err = c.DeleteDeviceRegistry(context.Background(), request)

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

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

}

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

	var formattedName string = fmt.Sprintf("projects/%s/locations/%s/registries/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]")
	var request = &iotpb.DeleteDeviceRegistryRequest{
		Name: formattedName,
	}

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

	err = c.DeleteDeviceRegistry(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)
	}
}
func TestDeviceManagerListDeviceRegistries(t *testing.T) {
	var nextPageToken string = ""
	var deviceRegistriesElement *iotpb.DeviceRegistry = &iotpb.DeviceRegistry{}
	var deviceRegistries = []*iotpb.DeviceRegistry{deviceRegistriesElement}
	var expectedResponse = &iotpb.ListDeviceRegistriesResponse{
		NextPageToken:    nextPageToken,
		DeviceRegistries: deviceRegistries,
	}

	mockDeviceManager.err = nil
	mockDeviceManager.reqs = nil

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

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

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

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

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

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

	want := (interface{})(expectedResponse.DeviceRegistries[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 TestDeviceManagerListDeviceRegistriesError(t *testing.T) {
	errCode := codes.PermissionDenied
	mockDeviceManager.err = gstatus.Error(errCode, "test error")

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

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

	resp, err := c.ListDeviceRegistries(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 TestDeviceManagerCreateDevice(t *testing.T) {
	var id string = "id3355"
	var name string = "name3373707"
	var numId uint64 = 1034366860
	var blocked bool = true
	var expectedResponse = &iotpb.Device{
		Id:      id,
		Name:    name,
		NumId:   numId,
		Blocked: blocked,
	}

	mockDeviceManager.err = nil
	mockDeviceManager.reqs = nil

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

	var formattedParent string = fmt.Sprintf("projects/%s/locations/%s/registries/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]")
	var device *iotpb.Device = &iotpb.Device{}
	var request = &iotpb.CreateDeviceRequest{
		Parent: formattedParent,
		Device: device,
	}

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

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

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

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

	var formattedParent string = fmt.Sprintf("projects/%s/locations/%s/registries/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]")
	var device *iotpb.Device = &iotpb.Device{}
	var request = &iotpb.CreateDeviceRequest{
		Parent: formattedParent,
		Device: device,
	}

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

	resp, err := c.CreateDevice(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 TestDeviceManagerGetDevice(t *testing.T) {
	var id string = "id3355"
	var name2 string = "name2-1052831874"
	var numId uint64 = 1034366860
	var blocked bool = true
	var expectedResponse = &iotpb.Device{
		Id:      id,
		Name:    name2,
		NumId:   numId,
		Blocked: blocked,
	}

	mockDeviceManager.err = nil
	mockDeviceManager.reqs = nil

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

	var formattedName string = fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]", "[DEVICE]")
	var request = &iotpb.GetDeviceRequest{
		Name: formattedName,
	}

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

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

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

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

	var formattedName string = fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]", "[DEVICE]")
	var request = &iotpb.GetDeviceRequest{
		Name: formattedName,
	}

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

	resp, err := c.GetDevice(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 TestDeviceManagerUpdateDevice(t *testing.T) {
	var id string = "id3355"
	var name string = "name3373707"
	var numId uint64 = 1034366860
	var blocked bool = true
	var expectedResponse = &iotpb.Device{
		Id:      id,
		Name:    name,
		NumId:   numId,
		Blocked: blocked,
	}

	mockDeviceManager.err = nil
	mockDeviceManager.reqs = nil

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

	var device *iotpb.Device = &iotpb.Device{}
	var updateMask *field_maskpb.FieldMask = &field_maskpb.FieldMask{}
	var request = &iotpb.UpdateDeviceRequest{
		Device:     device,
		UpdateMask: updateMask,
	}

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

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

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

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

	var device *iotpb.Device = &iotpb.Device{}
	var updateMask *field_maskpb.FieldMask = &field_maskpb.FieldMask{}
	var request = &iotpb.UpdateDeviceRequest{
		Device:     device,
		UpdateMask: updateMask,
	}

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

	resp, err := c.UpdateDevice(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 TestDeviceManagerDeleteDevice(t *testing.T) {
	var expectedResponse *emptypb.Empty = &emptypb.Empty{}

	mockDeviceManager.err = nil
	mockDeviceManager.reqs = nil

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

	var formattedName string = fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]", "[DEVICE]")
	var request = &iotpb.DeleteDeviceRequest{
		Name: formattedName,
	}

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

	err = c.DeleteDevice(context.Background(), request)

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

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

}

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

	var formattedName string = fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]", "[DEVICE]")
	var request = &iotpb.DeleteDeviceRequest{
		Name: formattedName,
	}

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

	err = c.DeleteDevice(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)
	}
}
func TestDeviceManagerListDevices(t *testing.T) {
	var nextPageToken string = ""
	var devicesElement *iotpb.Device = &iotpb.Device{}
	var devices = []*iotpb.Device{devicesElement}
	var expectedResponse = &iotpb.ListDevicesResponse{
		NextPageToken: nextPageToken,
		Devices:       devices,
	}

	mockDeviceManager.err = nil
	mockDeviceManager.reqs = nil

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

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

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

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

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

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

	want := (interface{})(expectedResponse.Devices[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 TestDeviceManagerListDevicesError(t *testing.T) {
	errCode := codes.PermissionDenied
	mockDeviceManager.err = gstatus.Error(errCode, "test error")

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

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

	resp, err := c.ListDevices(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 TestDeviceManagerModifyCloudToDeviceConfig(t *testing.T) {
	var version int64 = 351608024
	var binaryData2 []byte = []byte("-37")
	var expectedResponse = &iotpb.DeviceConfig{
		Version:    version,
		BinaryData: binaryData2,
	}

	mockDeviceManager.err = nil
	mockDeviceManager.reqs = nil

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

	var formattedName string = fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]", "[DEVICE]")
	var binaryData []byte = []byte("40")
	var request = &iotpb.ModifyCloudToDeviceConfigRequest{
		Name:       formattedName,
		BinaryData: binaryData,
	}

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

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

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

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

	var formattedName string = fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]", "[DEVICE]")
	var binaryData []byte = []byte("40")
	var request = &iotpb.ModifyCloudToDeviceConfigRequest{
		Name:       formattedName,
		BinaryData: binaryData,
	}

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

	resp, err := c.ModifyCloudToDeviceConfig(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 TestDeviceManagerListDeviceConfigVersions(t *testing.T) {
	var expectedResponse *iotpb.ListDeviceConfigVersionsResponse = &iotpb.ListDeviceConfigVersionsResponse{}

	mockDeviceManager.err = nil
	mockDeviceManager.reqs = nil

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

	var formattedName string = fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]", "[DEVICE]")
	var request = &iotpb.ListDeviceConfigVersionsRequest{
		Name: formattedName,
	}

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

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

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

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

	var formattedName string = fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]", "[DEVICE]")
	var request = &iotpb.ListDeviceConfigVersionsRequest{
		Name: formattedName,
	}

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

	resp, err := c.ListDeviceConfigVersions(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 TestDeviceManagerListDeviceStates(t *testing.T) {
	var expectedResponse *iotpb.ListDeviceStatesResponse = &iotpb.ListDeviceStatesResponse{}

	mockDeviceManager.err = nil
	mockDeviceManager.reqs = nil

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

	var formattedName string = fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]", "[DEVICE]")
	var request = &iotpb.ListDeviceStatesRequest{
		Name: formattedName,
	}

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

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

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

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

	var formattedName string = fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]", "[DEVICE]")
	var request = &iotpb.ListDeviceStatesRequest{
		Name: formattedName,
	}

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

	resp, err := c.ListDeviceStates(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 TestDeviceManagerSetIamPolicy(t *testing.T) {
	var version int32 = 351608024
	var etag []byte = []byte("21")
	var expectedResponse = &iampb.Policy{
		Version: version,
		Etag:    etag,
	}

	mockDeviceManager.err = nil
	mockDeviceManager.reqs = nil

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

	var formattedResource string = fmt.Sprintf("projects/%s/locations/%s/registries/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]")
	var policy *iampb.Policy = &iampb.Policy{}
	var request = &iampb.SetIamPolicyRequest{
		Resource: formattedResource,
		Policy:   policy,
	}

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

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

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

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

	var formattedResource string = fmt.Sprintf("projects/%s/locations/%s/registries/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]")
	var policy *iampb.Policy = &iampb.Policy{}
	var request = &iampb.SetIamPolicyRequest{
		Resource: formattedResource,
		Policy:   policy,
	}

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

	resp, err := c.SetIamPolicy(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 TestDeviceManagerGetIamPolicy(t *testing.T) {
	var version int32 = 351608024
	var etag []byte = []byte("21")
	var expectedResponse = &iampb.Policy{
		Version: version,
		Etag:    etag,
	}

	mockDeviceManager.err = nil
	mockDeviceManager.reqs = nil

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

	var formattedResource string = fmt.Sprintf("projects/%s/locations/%s/registries/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]")
	var request = &iampb.GetIamPolicyRequest{
		Resource: formattedResource,
	}

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

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

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

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

	var formattedResource string = fmt.Sprintf("projects/%s/locations/%s/registries/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]")
	var request = &iampb.GetIamPolicyRequest{
		Resource: formattedResource,
	}

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

	resp, err := c.GetIamPolicy(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 TestDeviceManagerTestIamPermissions(t *testing.T) {
	var expectedResponse *iampb.TestIamPermissionsResponse = &iampb.TestIamPermissionsResponse{}

	mockDeviceManager.err = nil
	mockDeviceManager.reqs = nil

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

	var formattedResource string = fmt.Sprintf("projects/%s/locations/%s/registries/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]")
	var permissions []string = nil
	var request = &iampb.TestIamPermissionsRequest{
		Resource:    formattedResource,
		Permissions: permissions,
	}

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

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

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

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

	var formattedResource string = fmt.Sprintf("projects/%s/locations/%s/registries/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]")
	var permissions []string = nil
	var request = &iampb.TestIamPermissionsRequest{
		Resource:    formattedResource,
		Permissions: permissions,
	}

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

	resp, err := c.TestIamPermissions(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 TestDeviceManagerSendCommandToDevice(t *testing.T) {
	var expectedResponse *iotpb.SendCommandToDeviceResponse = &iotpb.SendCommandToDeviceResponse{}

	mockDeviceManager.err = nil
	mockDeviceManager.reqs = nil

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

	var formattedName string = fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]", "[DEVICE]")
	var binaryData []byte = []byte("40")
	var request = &iotpb.SendCommandToDeviceRequest{
		Name:       formattedName,
		BinaryData: binaryData,
	}

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

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

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

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

	var formattedName string = fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]", "[DEVICE]")
	var binaryData []byte = []byte("40")
	var request = &iotpb.SendCommandToDeviceRequest{
		Name:       formattedName,
		BinaryData: binaryData,
	}

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

	resp, err := c.SendCommandToDevice(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 TestDeviceManagerBindDeviceToGateway(t *testing.T) {
	var expectedResponse *iotpb.BindDeviceToGatewayResponse = &iotpb.BindDeviceToGatewayResponse{}

	mockDeviceManager.err = nil
	mockDeviceManager.reqs = nil

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

	var formattedParent string = fmt.Sprintf("projects/%s/locations/%s/registries/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]")
	var gatewayId string = "gatewayId955798774"
	var deviceId string = "deviceId25209764"
	var request = &iotpb.BindDeviceToGatewayRequest{
		Parent:    formattedParent,
		GatewayId: gatewayId,
		DeviceId:  deviceId,
	}

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

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

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

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

	var formattedParent string = fmt.Sprintf("projects/%s/locations/%s/registries/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]")
	var gatewayId string = "gatewayId955798774"
	var deviceId string = "deviceId25209764"
	var request = &iotpb.BindDeviceToGatewayRequest{
		Parent:    formattedParent,
		GatewayId: gatewayId,
		DeviceId:  deviceId,
	}

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

	resp, err := c.BindDeviceToGateway(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 TestDeviceManagerUnbindDeviceFromGateway(t *testing.T) {
	var expectedResponse *iotpb.UnbindDeviceFromGatewayResponse = &iotpb.UnbindDeviceFromGatewayResponse{}

	mockDeviceManager.err = nil
	mockDeviceManager.reqs = nil

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

	var formattedParent string = fmt.Sprintf("projects/%s/locations/%s/registries/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]")
	var gatewayId string = "gatewayId955798774"
	var deviceId string = "deviceId25209764"
	var request = &iotpb.UnbindDeviceFromGatewayRequest{
		Parent:    formattedParent,
		GatewayId: gatewayId,
		DeviceId:  deviceId,
	}

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

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

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

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

	var formattedParent string = fmt.Sprintf("projects/%s/locations/%s/registries/%s", "[PROJECT]", "[LOCATION]", "[REGISTRY]")
	var gatewayId string = "gatewayId955798774"
	var deviceId string = "deviceId25209764"
	var request = &iotpb.UnbindDeviceFromGatewayRequest{
		Parent:    formattedParent,
		GatewayId: gatewayId,
		DeviceId:  deviceId,
	}

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

	resp, err := c.UnbindDeviceFromGateway(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
}
