vitess.io/vitess@v0.16.2/go/test/fuzzing/vttablet_fuzzer.go (about)

     1  //go:build gofuzz
     2  // +build gofuzz
     3  
     4  /*
     5  Copyright 2021 The Vitess Authors.
     6  Licensed under the Apache License, Version 2.0 (the "License");
     7  you may not use this file except in compliance with the License.
     8  You may obtain a copy of the License at
     9      http://www.apache.org/licenses/LICENSE-2.0
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package fuzzing
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"net"
    23  	"testing"
    24  
    25  	"google.golang.org/grpc"
    26  
    27  	"vitess.io/vitess/go/vt/vttablet/grpctmclient"
    28  	"vitess.io/vitess/go/vt/vttablet/grpctmserver"
    29  	"vitess.io/vitess/go/vt/vttablet/tmrpctest"
    30  
    31  	fuzz "github.com/AdaLogics/go-fuzz-headers"
    32  
    33  	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
    34  )
    35  
    36  func onceInit() {
    37  	testing.Init()
    38  }
    39  
    40  // createTablets creates a slice of Tablets that can
    41  // be used by the fuzz targets.
    42  func (fs *fuzzStore) createTablets(f *fuzz.ConsumeFuzzer) error {
    43  	tabletCount, err := f.GetInt()
    44  	if err != nil {
    45  		return err
    46  	}
    47  	tabletCount = tabletCount % 40
    48  	if tabletCount == 0 {
    49  		return fmt.Errorf("We don't need a nil-len list")
    50  	}
    51  	tablets := make([]*topodatapb.Tablet, 0)
    52  	for i := 0; i < tabletCount; i++ {
    53  		tablet := &topodatapb.Tablet{}
    54  		err = f.GenerateStruct(tablet)
    55  		if err != nil {
    56  			return err
    57  		}
    58  		tablets = append(tablets, tablet)
    59  	}
    60  	fs.tablets = tablets
    61  	return nil
    62  }
    63  
    64  // createTabletAliases creates a slice of TabletAliases that can
    65  // be used by the fuzz targets.
    66  func (fs *fuzzStore) createTabletAliases(f *fuzz.ConsumeFuzzer) error {
    67  	tabletAliasCount, err := f.GetInt()
    68  	if err != nil {
    69  		return err
    70  	}
    71  	tabletAliasCount = tabletAliasCount % 40
    72  	if tabletAliasCount == 0 {
    73  		return fmt.Errorf("We don't need a nil-len list")
    74  	}
    75  	tabletAliases := make([]*topodatapb.TabletAlias, 0)
    76  	for i := 0; i < tabletAliasCount; i++ {
    77  		tabletAlias := &topodatapb.TabletAlias{}
    78  		err = f.GenerateStruct(tabletAlias)
    79  		if err != nil {
    80  			return err
    81  		}
    82  		tabletAliases = append(tabletAliases, tabletAlias)
    83  	}
    84  	fs.tabletAliases = tabletAliases
    85  	return nil
    86  }
    87  
    88  // createStrings creates a slice of strings that can be used
    89  // by the fuzz tagets.
    90  func (fs *fuzzStore) createStrings(f *fuzz.ConsumeFuzzer) error {
    91  	stringCount, err := f.GetInt()
    92  	if err != nil {
    93  		return err
    94  	}
    95  	stringCount = stringCount % 100
    96  	if stringCount == 0 {
    97  		return fmt.Errorf("We don't need a nil-len list")
    98  	}
    99  	stringSlice := make([]string, 0)
   100  	for i := 0; i < stringCount; i++ {
   101  		newString, err := f.GetString()
   102  		if err != nil {
   103  			return err
   104  		}
   105  		stringSlice = append(stringSlice, newString)
   106  	}
   107  	fs.miscStrings = stringSlice
   108  	return nil
   109  }
   110  
   111  // createBytes creates a slice of byte slices that can be used
   112  // by the fuzz targets.
   113  func (fs *fuzzStore) createBytes(f *fuzz.ConsumeFuzzer) error {
   114  	bytesCount, err := f.GetInt()
   115  	if err != nil {
   116  		return err
   117  	}
   118  	bytesCount = bytesCount % 40
   119  	if bytesCount == 0 {
   120  		return fmt.Errorf("We don't need a nil-len list")
   121  	}
   122  	byteSlice := make([][]byte, 0)
   123  	for i := 0; i < bytesCount; i++ {
   124  		newBytes, err := f.GetBytes()
   125  		if err != nil {
   126  			return err
   127  		}
   128  		byteSlice = append(byteSlice, newBytes)
   129  	}
   130  	fs.miscBytes = byteSlice
   131  	return nil
   132  }
   133  
   134  // createInts creates a list of ints that can be used
   135  // by the fuzz targets.
   136  func (fs *fuzzStore) createInts(f *fuzz.ConsumeFuzzer) error {
   137  	intCount, err := f.GetInt()
   138  	if err != nil {
   139  		return err
   140  	}
   141  	intCount = intCount % 40
   142  	if intCount == 0 {
   143  		return fmt.Errorf("We don't need a nil-len list")
   144  	}
   145  	intSlice := make([]int, 0)
   146  	for i := 0; i < intCount; i++ {
   147  		newInt, err := f.GetInt()
   148  		if err != nil {
   149  			return err
   150  		}
   151  		intSlice = append(intSlice, newInt)
   152  	}
   153  	fs.miscInts = intSlice
   154  	return nil
   155  }
   156  
   157  // createExecutionOrder creates an array of ints that will later
   158  // be used to determine the order in which we call our fuzz targets.
   159  func (fs *fuzzStore) createExecutionOrder(f *fuzz.ConsumeFuzzer) error {
   160  	intCount, err := f.GetInt()
   161  	if err != nil {
   162  		return err
   163  	}
   164  	intCount = intCount % 60
   165  	if intCount == 0 {
   166  		return fmt.Errorf("We don't need a nil-len list")
   167  	}
   168  	executionOrder := make([]int, 0)
   169  	for i := 0; i < intCount; i++ {
   170  		newInt, err := f.GetInt()
   171  		if err != nil {
   172  			return err
   173  		}
   174  		executionOrder = append(executionOrder, newInt)
   175  	}
   176  	fs.executionOrder = executionOrder
   177  	return nil
   178  }
   179  
   180  type fuzzStore struct {
   181  	tablets        []*topodatapb.Tablet
   182  	tabletAliases  []*topodatapb.TabletAlias
   183  	miscStrings    []string
   184  	miscBytes      [][]byte
   185  	miscInts       []int
   186  	client         *grpctmclient.Client
   187  	executionOrder []int
   188  }
   189  
   190  // newFuzzStore creates a store of the data that is needed
   191  // for the fuzz targets in FuzzGRPCTMServer. The reason
   192  // a store is created is because the set up of the server
   193  // comes with a big expense, and having data ready to pass
   194  // to the targets improves efficiency.
   195  func newFuzzStore(f *fuzz.ConsumeFuzzer) (*fuzzStore, error) {
   196  	fs := &fuzzStore{}
   197  
   198  	err := fs.createTablets(f)
   199  	if err != nil {
   200  		return nil, err
   201  	}
   202  
   203  	err = fs.createTabletAliases(f)
   204  	if err != nil {
   205  		return nil, err
   206  	}
   207  
   208  	err = fs.createStrings(f)
   209  	if err != nil {
   210  		return nil, err
   211  	}
   212  
   213  	err = fs.createBytes(f)
   214  	if err != nil {
   215  		return nil, err
   216  	}
   217  
   218  	err = fs.createInts(f)
   219  	if err != nil {
   220  		return nil, err
   221  	}
   222  
   223  	err = fs.createExecutionOrder(f)
   224  	if err != nil {
   225  		return nil, err
   226  	}
   227  	return fs, nil
   228  }
   229  
   230  func (fs *fuzzStore) getTablet() (*topodatapb.Tablet, error) {
   231  	if len(fs.tablets) == 0 {
   232  		return nil, fmt.Errorf("Not enough tablets")
   233  	}
   234  	tablet := fs.tablets[0]
   235  	fs.tablets = fs.tablets[1:]
   236  	return tablet, nil
   237  }
   238  
   239  func (fs *fuzzStore) getString() (string, error) {
   240  	if len(fs.miscStrings) == 0 {
   241  		return "", fmt.Errorf("Not enough tablets")
   242  	}
   243  	returnString := fs.miscStrings[0]
   244  	fs.miscStrings = fs.miscStrings[1:]
   245  	return returnString, nil
   246  }
   247  
   248  func (fs *fuzzStore) getInt() (int, error) {
   249  	if len(fs.miscInts) == 0 {
   250  		return 0, fmt.Errorf("Not enough tablets")
   251  	}
   252  	returnInt := fs.miscInts[0]
   253  	fs.miscInts = fs.miscInts[1:]
   254  	return returnInt, nil
   255  }
   256  
   257  func (fs *fuzzStore) getBytes() ([]byte, error) {
   258  	if len(fs.miscBytes) == 0 {
   259  		return nil, fmt.Errorf("Not enough tablets")
   260  	}
   261  	returnBytes := fs.miscBytes[0]
   262  	fs.miscBytes = fs.miscBytes[1:]
   263  	return returnBytes, nil
   264  }
   265  
   266  func (fs *fuzzStore) getTabletAlias() (*topodatapb.TabletAlias, error) {
   267  	if len(fs.tabletAliases) == 0 {
   268  		return nil, fmt.Errorf("Not enough tablets")
   269  	}
   270  	tabletAlias := fs.tabletAliases[0]
   271  	fs.tabletAliases = fs.tabletAliases[1:]
   272  	return tabletAlias, nil
   273  }
   274  
   275  // callExecuteFetchAsApp implements a wrapper
   276  // for fuzzing ExecuteFetchAsApp
   277  func (fs *fuzzStore) callExecuteFetchAsApp() error {
   278  	tablet, err := fs.getTablet()
   279  	if err != nil {
   280  		return err
   281  	}
   282  	byteQuery, err := fs.getBytes()
   283  	if err != nil {
   284  		return err
   285  	}
   286  	maxRows, err := fs.getInt()
   287  	if err != nil {
   288  		return err
   289  	}
   290  	_, _ = fs.client.ExecuteFetchAsApp(context.Background(), tablet, false, byteQuery, maxRows)
   291  	return nil
   292  }
   293  
   294  // callInitPrimary implements a wrapper
   295  // for fuzzing InitPrimary
   296  func (fs *fuzzStore) callInitPrimary() error {
   297  	tablet, err := fs.getTablet()
   298  	if err != nil {
   299  		return err
   300  	}
   301  	_, _ = fs.client.InitPrimary(context.Background(), tablet, false)
   302  	return nil
   303  }
   304  
   305  // callResetReplication implements a wrapper
   306  // for fuzzing ResetReplication
   307  func (fs *fuzzStore) callResetReplication() error {
   308  	tablet, err := fs.getTablet()
   309  	if err != nil {
   310  		return err
   311  	}
   312  	_ = fs.client.ResetReplication(context.Background(), tablet)
   313  	return nil
   314  }
   315  
   316  // callGetReplicas implements a wrapper
   317  // for fuzzing GetReplicas
   318  func (fs *fuzzStore) callGetReplicas() error {
   319  	tablet, err := fs.getTablet()
   320  	if err != nil {
   321  		return err
   322  	}
   323  	_, _ = fs.client.GetReplicas(context.Background(), tablet)
   324  	return nil
   325  }
   326  
   327  // callStartReplication implements a wrapper
   328  // for fuzzing StartReplication
   329  func (fs *fuzzStore) callStartReplication() error {
   330  	tablet, err := fs.getTablet()
   331  	if err != nil {
   332  		return err
   333  	}
   334  	_ = fs.client.StartReplication(context.Background(), tablet, false)
   335  	return nil
   336  }
   337  
   338  // callStopReplication implements a wrapper
   339  // for fuzzing StopReplication
   340  func (fs *fuzzStore) callStopReplication() error {
   341  	tablet, err := fs.getTablet()
   342  	if err != nil {
   343  		return err
   344  	}
   345  	_ = fs.client.StopReplication(context.Background(), tablet)
   346  	return nil
   347  }
   348  
   349  // callPrimaryPosition implements a wrapper
   350  // for fuzzing PrimaryPosition
   351  func (fs *fuzzStore) callPrimaryPosition() error {
   352  	tablet, err := fs.getTablet()
   353  	if err != nil {
   354  		return err
   355  	}
   356  	_, _ = fs.client.PrimaryPosition(context.Background(), tablet)
   357  	return nil
   358  }
   359  
   360  // callReplicationStatus implements a wrapper
   361  // for fuzzing ReplicationStatus
   362  func (fs *fuzzStore) callReplicationStatus() error {
   363  	tablet, err := fs.getTablet()
   364  	if err != nil {
   365  		return err
   366  	}
   367  	_, _ = fs.client.ReplicationStatus(context.Background(), tablet)
   368  	return nil
   369  }
   370  
   371  // callFullStatus implements a wrapper
   372  // for fuzzing FullStatus
   373  func (fs *fuzzStore) callFullStatus() error {
   374  	tablet, err := fs.getTablet()
   375  	if err != nil {
   376  		return err
   377  	}
   378  	_, _ = fs.client.FullStatus(context.Background(), tablet)
   379  	return nil
   380  }
   381  
   382  // callPrimaryStatus implements a wrapper
   383  // for fuzzing PrimaryStatus
   384  func (fs *fuzzStore) callPrimaryStatus() error {
   385  	tablet, err := fs.getTablet()
   386  	if err != nil {
   387  		return err
   388  	}
   389  	_, _ = fs.client.PrimaryStatus(context.Background(), tablet)
   390  	return nil
   391  }
   392  
   393  // callDemotePrimary implements a wrapper
   394  // for fuzzing DemotePrimary
   395  func (fs *fuzzStore) callDemotePrimary() error {
   396  	tablet, err := fs.getTablet()
   397  	if err != nil {
   398  		return err
   399  	}
   400  	_, _ = fs.client.DemotePrimary(context.Background(), tablet)
   401  	return nil
   402  }
   403  
   404  // callUndoDemotePrimary implements a wrapper
   405  // for fuzzing UndoDemotePrimary
   406  func (fs *fuzzStore) callUndoDemotePrimary() error {
   407  	tablet, err := fs.getTablet()
   408  	if err != nil {
   409  		return err
   410  	}
   411  	_ = fs.client.UndoDemotePrimary(context.Background(), tablet, false)
   412  	return nil
   413  }
   414  
   415  // callReplicaWasPromoted implements a wrapper
   416  // for fuzzing ReplicaWasPromoted
   417  func (fs *fuzzStore) callReplicaWasPromoted() error {
   418  	tablet, err := fs.getTablet()
   419  	if err != nil {
   420  		return err
   421  	}
   422  	_ = fs.client.ReplicaWasPromoted(context.Background(), tablet)
   423  	return nil
   424  }
   425  
   426  // callResetReplicationParameters implements a wrapper
   427  // for fuzzing ResetReplicationParameters
   428  func (fs *fuzzStore) callResetReplicationParameters() error {
   429  	tablet, err := fs.getTablet()
   430  	if err != nil {
   431  		return err
   432  	}
   433  	_ = fs.client.ResetReplicationParameters(context.Background(), tablet)
   434  	return nil
   435  }
   436  
   437  // callPromoteReplica implements a wrapper
   438  // for fuzzing PromoteReplica
   439  func (fs *fuzzStore) callPromoteReplica() error {
   440  	tablet, err := fs.getTablet()
   441  	if err != nil {
   442  		return err
   443  	}
   444  	_, _ = fs.client.PromoteReplica(context.Background(), tablet, false)
   445  	return nil
   446  }
   447  
   448  // callStopReplicationAndGetStatus implements a wrapper
   449  // for fuzzing StopReplicationAndGetStatus
   450  func (fs *fuzzStore) callStopReplicationAndGetStatus() error {
   451  	tablet, err := fs.getTablet()
   452  	if err != nil {
   453  		return err
   454  	}
   455  	_, _, _ = fs.client.StopReplicationAndGetStatus(context.Background(), tablet, 0)
   456  	return nil
   457  }
   458  
   459  // callReplicaWasRestarted implements a wrapper
   460  // for fuzzing ReplicaWasRestarted
   461  func (fs *fuzzStore) callReplicaWasRestarted() error {
   462  	tablet, err := fs.getTablet()
   463  	if err != nil {
   464  		return err
   465  	}
   466  	parent, err := fs.getTabletAlias()
   467  	if err != nil {
   468  		return err
   469  	}
   470  	_ = fs.client.ReplicaWasRestarted(context.Background(), tablet, parent)
   471  	return nil
   472  }
   473  
   474  // callWaitForPosition implements a wrapper
   475  // for fuzzing WaitForPosition
   476  func (fs *fuzzStore) callWaitForPosition() error {
   477  	tablet, err := fs.getTablet()
   478  	if err != nil {
   479  		return err
   480  	}
   481  	pos, err := fs.getString()
   482  	if err != nil {
   483  		return err
   484  	}
   485  	_ = fs.client.WaitForPosition(context.Background(), tablet, pos)
   486  	return nil
   487  }
   488  
   489  // callVReplicationExec implements a wrapper
   490  // for fuzzing VReplicationExec
   491  func (fs *fuzzStore) callVReplicationExec() error {
   492  	tablet, err := fs.getTablet()
   493  	if err != nil {
   494  		return err
   495  	}
   496  	query, err := fs.getString()
   497  	if err != nil {
   498  		return err
   499  	}
   500  	_, _ = fs.client.VReplicationExec(context.Background(), tablet, query)
   501  	return nil
   502  }
   503  
   504  // callVExec implements a wrapper
   505  // for fuzzing VExec
   506  func (fs *fuzzStore) callVExec() error {
   507  	tablet, err := fs.getTablet()
   508  	if err != nil {
   509  		return err
   510  	}
   511  	query, err := fs.getString()
   512  	if err != nil {
   513  		return err
   514  	}
   515  	workflow, err := fs.getString()
   516  	if err != nil {
   517  		return err
   518  	}
   519  	keyspace, err := fs.getString()
   520  	if err != nil {
   521  		return err
   522  	}
   523  	_, _ = fs.client.VExec(context.Background(), tablet, query, workflow, keyspace)
   524  	return nil
   525  }
   526  
   527  // callVReplicationWaitForPos implements a wrapper
   528  // for fuzzing VReplicationWaitForPos
   529  func (fs *fuzzStore) callVReplicationWaitForPos() error {
   530  	tablet, err := fs.getTablet()
   531  	if err != nil {
   532  		return err
   533  	}
   534  	pos, err := fs.getString()
   535  	if err != nil {
   536  		return err
   537  	}
   538  	timeCreatedNS, err := fs.getInt()
   539  	if err != nil {
   540  		return err
   541  	}
   542  	_ = fs.client.VReplicationWaitForPos(context.Background(), tablet, timeCreatedNS, pos)
   543  	return nil
   544  }
   545  
   546  // callSetReplicationSource implements a wrapper
   547  // for fuzzing SetReplicationSource
   548  func (fs *fuzzStore) callSetReplicationSource() error {
   549  	tablet, err := fs.getTablet()
   550  	if err != nil {
   551  		return err
   552  	}
   553  	pos, err := fs.getString()
   554  	if err != nil {
   555  		return err
   556  	}
   557  	timeCreatedNS, err := fs.getInt()
   558  	if err != nil {
   559  		return err
   560  	}
   561  	parent, err := fs.getTabletAlias()
   562  	if err != nil {
   563  		return err
   564  	}
   565  	_ = fs.client.SetReplicationSource(context.Background(), tablet, parent, int64(timeCreatedNS), pos, false, false)
   566  	return nil
   567  }
   568  
   569  // callInitReplica implements a wrapper
   570  // for fuzzing InitReplica
   571  func (fs *fuzzStore) callInitReplica() error {
   572  	tablet, err := fs.getTablet()
   573  	if err != nil {
   574  		return err
   575  	}
   576  	timeCreatedNS, err := fs.getInt()
   577  	if err != nil {
   578  		return err
   579  	}
   580  	parent, err := fs.getTabletAlias()
   581  	if err != nil {
   582  		return err
   583  	}
   584  	replicationPosition, err := fs.getString()
   585  	if err != nil {
   586  		return err
   587  	}
   588  	_ = fs.client.InitReplica(context.Background(), tablet, parent, replicationPosition, int64(timeCreatedNS), false)
   589  	return nil
   590  }
   591  
   592  // callPopulateReparentJournal implements a wrapper
   593  // for fuzzing PopulateReparentJournal
   594  func (fs *fuzzStore) callPopulateReparentJournal() error {
   595  	tablet, err := fs.getTablet()
   596  	if err != nil {
   597  		return err
   598  	}
   599  	timeCreatedNS, err := fs.getInt()
   600  	if err != nil {
   601  		return err
   602  	}
   603  	tabletAlias, err := fs.getTabletAlias()
   604  	if err != nil {
   605  		return err
   606  	}
   607  	actionName, err := fs.getString()
   608  	if err != nil {
   609  		return err
   610  	}
   611  	pos, err := fs.getString()
   612  	if err != nil {
   613  		return err
   614  	}
   615  	_ = fs.client.PopulateReparentJournal(context.Background(), tablet, int64(timeCreatedNS), actionName, tabletAlias, pos)
   616  	return nil
   617  }
   618  
   619  // executeInRandomOrder calls the fuzz targets in
   620  // the order specified by f.executionOrder
   621  func (fs *fuzzStore) executeInRandomOrder() {
   622  	maxTargets := 24
   623  	for _, execInt := range fs.executionOrder {
   624  		var err error
   625  		switch execInt % maxTargets {
   626  		case 0:
   627  			err = fs.callInitPrimary()
   628  		case 1:
   629  			err = fs.callResetReplication()
   630  		case 2:
   631  			err = fs.callGetReplicas()
   632  		case 3:
   633  			err = fs.callStartReplication()
   634  		case 4:
   635  			err = fs.callStopReplication()
   636  		case 5:
   637  			err = fs.callPrimaryPosition()
   638  		case 7:
   639  			err = fs.callReplicationStatus()
   640  		case 8:
   641  			err = fs.callPrimaryStatus()
   642  		case 9:
   643  			err = fs.callDemotePrimary()
   644  		case 11:
   645  			err = fs.callUndoDemotePrimary()
   646  		case 12:
   647  			err = fs.callReplicaWasPromoted()
   648  		case 13:
   649  			err = fs.callPromoteReplica()
   650  		case 14:
   651  			err = fs.callReplicaWasRestarted()
   652  		case 15:
   653  			err = fs.callWaitForPosition()
   654  		case 16:
   655  			err = fs.callVReplicationExec()
   656  		case 17:
   657  			err = fs.callVExec()
   658  		case 18:
   659  			err = fs.callStopReplicationAndGetStatus()
   660  		case 19:
   661  			err = fs.callExecuteFetchAsApp()
   662  		case 20:
   663  			err = fs.callVReplicationWaitForPos()
   664  		case 21:
   665  			err = fs.callSetReplicationSource()
   666  		case 22:
   667  			err = fs.callInitReplica()
   668  		case 23:
   669  			err = fs.callPopulateReparentJournal()
   670  		case 24:
   671  			err = fs.callResetReplicationParameters()
   672  		case 25:
   673  			err = fs.callFullStatus()
   674  		}
   675  
   676  		// err means that fuzzStore doesn't have any data
   677  		// to pass to the target so we return here
   678  		if err != nil {
   679  			return
   680  		}
   681  	}
   682  }
   683  
   684  // FuzzGRPCTMServer implements the fuzzer.
   685  func FuzzGRPCTMServer(data []byte) int {
   686  	initter.Do(onceInit)
   687  	f := fuzz.NewConsumer(data)
   688  	fs, err := newFuzzStore(f)
   689  	if err != nil {
   690  		return 0
   691  	}
   692  	t := &testing.T{}
   693  
   694  	// Listen on a random port
   695  	listener, err := net.Listen("tcp", "127.0.0.1:0")
   696  	if err != nil {
   697  		return 0
   698  	}
   699  	defer listener.Close()
   700  
   701  	host := listener.Addr().(*net.TCPAddr).IP.String()
   702  	port := int32(listener.Addr().(*net.TCPAddr).Port)
   703  	_, _ = host, port
   704  	for _, tablet := range fs.tablets {
   705  		tablet.Hostname = host
   706  		tablet.PortMap = map[string]int32{
   707  			"grpc": port,
   708  		}
   709  	}
   710  	s := grpc.NewServer()
   711  	fakeTM := tmrpctest.NewFakeRPCTM(t)
   712  	grpctmserver.RegisterForTest(s, fakeTM)
   713  	go s.Serve(listener)
   714  	defer s.Stop()
   715  
   716  	// Create a gRPC client to talk to the fake tablet.
   717  	client := grpctmclient.NewClient()
   718  	defer client.Close()
   719  	fs.client = client
   720  
   721  	// Call the targets in random order.
   722  	fs.executeInRandomOrder()
   723  
   724  	return 1
   725  }