func TestResolveConflictsWithMultipleLevelDeps(t *testing.T) {
	r := commonTestlibExampleReplica()
	r.InstanceMatrix[0][6] = NewInstance(r, 0, 6)
	r.InstanceMatrix[0][6].status = committed
	r.InstanceMatrix[0][6].deps = message.Dependencies{4, 5, 6, 7, 8}
	for i := range r.InstanceMatrix {
		r.InstanceMatrix[i][i+4] = NewInstance(r, uint8(i), uint64(i+4))
		r.InstanceMatrix[i][i+4].status = committed
	}
	r.InstanceMatrix[0][4].deps = message.Dependencies{2, 0, 0, 0, 0}
	r.InstanceMatrix[1][5].deps = message.Dependencies{2, 3, 0, 0, 0}
	r.InstanceMatrix[2][6].deps = message.Dependencies{2, 3, 4, 0, 0}
	r.InstanceMatrix[3][7].deps = message.Dependencies{2, 3, 4, 5, 0}
	r.InstanceMatrix[4][8].deps = message.Dependencies{2, 3, 4, 5, 6}
	for i := range r.InstanceMatrix {
		r.InstanceMatrix[i][i+2] = NewInstance(r, uint8(i), uint64(i+2))
		r.InstanceMatrix[i][i+2].status = committed
	}
	assert.True(t, r.resolveConflicts(r.InstanceMatrix[0][6]))
	sccResultInstances := make([]*Instance, 0)
	for _, instances := range r.sccResults {
		sccResultInstances = append(sccResultInstances, instances...)
	}
	assert.Equal(t, len(sccResultInstances), 11)
	j := 0
	for i := range r.InstanceMatrix {
		assert.Equal(t, sccResultInstances[j], r.InstanceMatrix[i][i+2])
		j++
		assert.Equal(t, sccResultInstances[j], r.InstanceMatrix[i][i+4])
		j++
	}
	assert.Equal(t, sccResultInstances[j], r.InstanceMatrix[0][6])
}
***************************************************************
***** 3, mutiple levels of depth of deps, (acyclic graph) *****
***************************************************************
InstanceMatrix:

2 <---|         |---4 <------ 6
3 <---|         |---5 <-----/
4 <---| mapping |---6 <----/
5 <---|         |---7 <---/
6 <---|         |---8 <--/
package replica
import (
	"fmt"
	"testing"
	"time"
	"github.com/go-distributed/epaxos"
	"github.com/go-distributed/epaxos/message"
	"github.com/go-distributed/epaxos/test"
	"github.com/go-distributed/epaxos/transporter"
	"github.com/stretchr/testify/assert"
)
var _ = fmt.Printf
func TestNewReplica(t *testing.T) {
	param := &Param{
		ReplicaId:    3,
		Size:         5,
		StateMachine: new(test.DummySM),
		Transporter:  transporter.NewDummyTR(3, 5),
	}
	r, _ := New(param)
	assert.True(t, r.Id == 3)
	assert.True(t, r.Size == 5)
	assert.True(t, len(r.MaxInstanceNum) == 5)
	assert.True(t, len(r.InstanceMatrix) == 5)
	assert.Equal(t, r.StateMachine, new(test.DummySM))
	assert.True(t, r.Epoch == 1)
	for i := range r.InstanceMatrix {
		assert.True(t, len(r.InstanceMatrix[i]) == defaultInstancesLength)
	}
	param.Size = 4
	_, err := New(param)
	assert.NotNil(t, err)
}
func TestMakeInitialBallot(t *testing.T) {
	param := &Param{
		ReplicaId:    3,
		Size:         5,
		StateMachine: new(test.DummySM),
		Transporter:  transporter.NewDummyTR(3, 5),
	}
	r, _ := New(param)
	r.Epoch = 3
	b := r.makeInitialBallot()
	assert.Equal(t, b, message.NewBallot(3, 0, 3))
}
func depsTestSetupReplica() (r *Replica, i *Instance) {
	param := &Param{
		ReplicaId:    4,
		Size:         5,
		StateMachine: new(test.DummySM),
		Transporter:  transporter.NewDummyTR(4, 5),
	}
	r, _ = New(param)
	for i := 0; i < 5; i++ {
		r.MaxInstanceNum[i] = uint64(conflictNotFound + 1 + uint64(i))
		instance := NewInstance(r, r.Id, conflictNotFound+1+uint64(i))
		instance.cmds = commonTestlibExampleCommands().Clone()
		r.InstanceMatrix[i][instance.id] = instance
	}
	i = NewInstance(r, r.Id, 6)
	return
}
func TestInitInstance(t *testing.T) {
	r, i := depsTestSetupReplica()
	Cmds := commonTestlibExampleCommands()
	r.initInstance(Cmds, i)
	assert.Equal(t, i.cmds, Cmds)
	assert.Equal(t, i.deps, message.Dependencies{1, 2, 3, 4, 5})
}
func TestUpdateInstance(t *testing.T) {
	r, i := depsTestSetupReplica()
	cmds := commonTestlibExampleCommands()
	deps := message.Dependencies{1, 2, 3, 4, 5}
	changed := r.updateInstance(cmds, deps, r.Id, i)
	assert.False(t, changed)
	assert.Equal(t, i.deps, deps)
	emptyDeps := message.Dependencies{2, 0, 0, 0, 0}
	expectedDeps := message.Dependencies{2, 2, 3, 4, 5}  
	changed = r.updateInstance(cmds, emptyDeps, 0, i)
	assert.True(t, changed)
	assert.Equal(t, i.deps, expectedDeps)
}
func TestSccStack(t *testing.T) {
	i := commonTestlibExampleCommittedInstance()
	iClone := commonTestlibCloneInstance(i)
	iClone.ballot = iClone.ballot.IncNumClone()
	r := i.replica
	r.pushSccStack(i)
	r.pushSccStack(iClone)
	assert.True(t, r.inSccStack(i))
	assert.True(t, r.inSccStack(iClone))
	iPop := r.popSccStack()
	assert.Equal(t, iClone, iPop)
	assert.NotEqual(t, i, iPop)
	assert.False(t, r.inSccStack(iClone))
	assert.True(t, r.inSccStack(i))
	iPop = r.popSccStack()
	assert.Equal(t, i, iPop)
	assert.NotEqual(t, iClone, iPop)
	assert.False(t, r.inSccStack(i))
}
func TestResolveConflictsWithNoDeps(t *testing.T) {
	r := commonTestlibExampleReplica()
	for i := range r.InstanceMatrix {
		r.InstanceMatrix[i][1] = NewInstance(r, uint8(i), 1)
	}
	assert.Panics(t, func() { r.resolveConflicts(r.InstanceMatrix[0][1]) })
	r.InstanceMatrix[0][1].status = committed
	assert.True(t, r.resolveConflicts(r.InstanceMatrix[0][1]))
	sccResultInstances := make([]*Instance, 0)
	for _, instances := range r.sccResults {
		sccResultInstances = append(sccResultInstances, instances...)
	}
	assert.Equal(t, len(sccResultInstances), 1)
	assert.Equal(t, sccResultInstances[0], r.InstanceMatrix[0][1])
}
func TestResolveConflictsWithSimpleDeps(t *testing.T) {
	r := commonTestlibExampleReplica()
	for i := range r.InstanceMatrix {
		r.InstanceMatrix[i][i+2] = NewInstance(r, uint8(i), uint64(i+2))
		r.InstanceMatrix[i][i+2].status = committed
	}
	r.InstanceMatrix[0][3] = NewInstance(r, 0, 3)
	r.InstanceMatrix[0][3].deps = message.Dependencies{2, 3, 4, 5, 6}
	r.InstanceMatrix[0][3].status = committed
	assert.True(t, r.resolveConflicts(r.InstanceMatrix[0][3]))
	sccResultInstances := make([]*Instance, 0)
	for _, instances := range r.sccResults {
		sccResultInstances = append(sccResultInstances, instances...)
	}
	assert.Equal(t, len(sccResultInstances), 6)
	i := 0
	for i = range r.InstanceMatrix {
		assert.Equal(t, sccResultInstances[i], r.InstanceMatrix[i][i+2])
	}
	i++
	assert.Equal(t, sccResultInstances[i], r.InstanceMatrix[0][3])
}