func makeClients(numClient int, testKeys []byte, cfg api.Configer) {
	for i := 0; i < numClient; i++ {
		au, _ := authen.New([]api.AuthenticationRole{api.ClientAuthen}, testClientID, bytes.NewBuffer(testKeys))
		conn := newClientSideConnector()
		stack := &testClientStack{conn, au}
		clientStacks = append(clientStacks, stack)
		client, _ := cl.New(testClientID, cfg.N(), cfg.F(), stack)
		clients = append(clients, client)
	}
}
Initialize a given number of client instances.
package minbft_test
import (
	"bytes"
	"fmt"
	"log"
	"testing"
	"text/template"
	"time"
	"github.com/hyperledger-labs/minbft/api"
	cl "github.com/hyperledger-labs/minbft/client"
	minbft "github.com/hyperledger-labs/minbft/core"
	authen "github.com/hyperledger-labs/minbft/sample/authentication"
	"github.com/hyperledger-labs/minbft/sample/config"
	"github.com/hyperledger-labs/minbft/sample/conn/common/replicastub"
	dummyConnector "github.com/hyperledger-labs/minbft/sample/conn/dummy/connector"
	"github.com/hyperledger-labs/minbft/sample/requestconsumer"
	"github.com/stretchr/testify/assert"
)
const (
	testClientID = 0
	waitDuration = 200 * time.Millisecond
	usigEnclaveFile = "../usig/sgx/enclave/libusig.signed.so"
)
type testReplicaStack struct {
	api.ReplicaConnector
	api.Authenticator
	*requestconsumer.SimpleLedger
}
type testClientStack struct {
	api.ReplicaConnector
	api.Authenticator
}
var (
	replicas      []api.Replica
	replicaStacks []*testReplicaStack
	clients      []cl.Client
	clientStacks []*testClientStack
	replicaStubs []replicastub.ReplicaStub
	testRequestMessage = []byte("test request message")
)
const cfgTemplate = `
protocol:
  "n": {{.N}}
  f: {{getF .N}}
  checkpointPeriod: 10
  logsize: 20
  timeout:
    request: 2s
    viewchange: 3s
`
func createTestCfg(numReplica int) []byte {
	var err error
	var testCfg bytes.Buffer
	t := template.New("cfgTemplate")
	t = t.Funcs(template.FuncMap{
		"getF": func(n int) int { return (n - 1) / 2 },
	})
	t = template.Must(t.Parse(cfgTemplate))
	if err = t.Execute(&testCfg, struct{ N int }{numReplica}); err != nil {
		panic(err)
	}
	return testCfg.Bytes()
}
func createTestKeys(numReplica, numClient int) []byte {
	var testKeys bytes.Buffer
	const testKeySpec = "ECDSA"
	if err := authen.GenerateTestnetKeys(&testKeys, &authen.TestnetKeyOpts{
		NumberReplicas:  numReplica,
		ReplicaKeySpec:  testKeySpec,
		ReplicaSecParam: 256,
		NumberClients:   numClient,
		ClientKeySpec:   testKeySpec,
		ClientSecParam:  256,
		UsigEnclaveFile: usigEnclaveFile,
	}); err != nil {
		log.Fatalf("Failed to generate testnet keys: %v", err)
	}
	return testKeys.Bytes()
}
func resetFixture() {
	replicas = nil
	replicaStacks = nil
	clients = nil
	clientStacks = nil
	replicaStubs = nil
}
func initTestnetPeers(numReplica int, numClient int) {
	resetFixture()
	testCfg := createTestCfg(numReplica)
	testKeys := createTestKeys(numReplica, numClient)
	cfg := config.New()  
	err := cfg.ReadConfig(bytes.NewBuffer(testCfg), "yaml")
	if err != nil {
		panic(err)
	}
	makeReplicas(numReplica, testKeys, cfg)
	makeClients(numClient, testKeys, cfg)
}
func makeReplicas(numReplica int, testKeys []byte, cfg api.Configer) {
	for i := 0; i < numReplica; i++ {
		replicaStubs = append(replicaStubs, replicastub.New())
	}
	for i := 0; i < numReplica; i++ {
		id := uint32(i)
		sigAuth, _ := authen.NewWithSGXUSIG([]api.AuthenticationRole{api.ReplicaAuthen, api.USIGAuthen}, id, bytes.NewBuffer(testKeys), usigEnclaveFile)
		ledger := requestconsumer.NewSimpleLedger()
		conn := newReplicaSideConnector(id)
		stack := &testReplicaStack{conn, sigAuth, ledger}
		replicaStacks = append(replicaStacks, stack)
		replica, _ := minbft.New(id, cfg, stack)
		replicas = append(replicas, replica)
		replicaStubs[i].AssignReplica(replica)
	}
}
func newReplicaSideConnector(replicaID uint32) api.ReplicaConnector {
	conn := dummyConnector.NewReplicaSide()
	for i, stub := range replicaStubs {
		id := uint32(i)
		if id == replicaID {
			continue
		}
		conn.AssignReplicaStub(id, stub)
	}
	return conn
}