From d4228f32b436f551e736079fe0f590405077652c Mon Sep 17 00:00:00 2001 From: Haoping Ku Date: Mon, 13 Aug 2018 18:09:30 +0800 Subject: core: add nack module (#41) --- core/negative-ack_test.go | 231 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 core/negative-ack_test.go (limited to 'core/negative-ack_test.go') diff --git a/core/negative-ack_test.go b/core/negative-ack_test.go new file mode 100644 index 0000000..87fcea0 --- /dev/null +++ b/core/negative-ack_test.go @@ -0,0 +1,231 @@ +// Copyright 2018 The dexon-consensus-core Authors +// This file is part of the dexon-consensus-core library. +// +// The dexon-consensus-core library is free software: you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// The dexon-consensus-core library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the dexon-consensus-core library. If not, see +// . + +package core + +import ( + "testing" + "time" + + "github.com/stretchr/testify/suite" + + "github.com/dexon-foundation/dexon-consensus-core/common" + "github.com/dexon-foundation/dexon-consensus-core/core/types" +) + +var ( + baseTime = time.Now().UTC() + timeDelay = 2 * time.Second + timeExpire = 100 * time.Millisecond +) + +type NegativeAckTest struct { + suite.Suite +} + +func (s *NegativeAckTest) SetupSuite() { + +} + +func (s *NegativeAckTest) SetupTest() { + +} + +func (s *NegativeAckTest) checkLastVotes( + vids []types.ValidatorID, + vs map[types.ValidatorID]map[types.ValidatorID]struct{}, + a [][]bool, +) { + + for i := 0; i < len(vids); i++ { + for j := 0; j < len(vids); j++ { + _, exist := vs[vids[i]][vids[j]] + s.Require().Equal(a[i][j], exist) + } + } +} + +func (s *NegativeAckTest) checkTimeDiff( + vids []types.ValidatorID, + ts map[types.ValidatorID]map[types.ValidatorID]time.Time, + a [][]int, +) { + + for i := 0; i < len(vids); i++ { + for j := 0; j < len(vids); j++ { + s.Require().Equal( + time.Duration(a[i][j])*timeDelay, + ts[vids[i]][vids[j]].Sub(baseTime), + ) + } + } +} + +func genTimestamp(vids []types.ValidatorID, a []int) map[types.ValidatorID]time.Time { + ts := map[types.ValidatorID]time.Time{} + for i := 0; i < len(vids); i++ { + ts[vids[i]] = baseTime.Add(time.Duration(a[i]) * timeDelay) + } + return ts +} + +func genTestNegativeAck(num int) (*negativeAck, []types.ValidatorID) { + vids := []types.ValidatorID{} + for i := 0; i < num; i++ { + vids = append(vids, types.ValidatorID{Hash: common.NewRandomHash()}) + } + n := newNegativeAck(vids[0]) + for i := 1; i < num; i++ { + n.addValidator(vids[i]) + } + return n, vids +} + +func (s *NegativeAckTest) TestProcessTimestamps() { + n, vids := genTestNegativeAck(4) + n.setTimeDelay(timeDelay) + n.setTimeExpire(timeExpire) + + n.processTimestamps(vids[0], genTimestamp(vids, []int{1, 1, 1, 0})) + s.checkTimeDiff(vids, n.timeDiffs[vids[0]], [][]int{ + {1, 1, 1, 0}, + {1, 1, 1, 0}, + {1, 1, 1, 0}, + {1, 1, 1, 0}, + }) + s.checkLastVotes(vids, n.lastVotes, [][]bool{ + {false, false, false, false}, + {false, false, false, false}, + {false, false, false, false}, + {false, false, false, false}, + }) + + n.processTimestamps(vids[0], genTimestamp(vids, []int{3, 1, 2, 1})) + s.checkTimeDiff(vids, n.timeDiffs[vids[0]], [][]int{ + {3, 1, 2, 1}, + {1, 1, 1, 0}, + {3, 1, 2, 1}, + {3, 1, 2, 1}, + }) + s.checkLastVotes(vids, n.lastVotes, [][]bool{ + {false, false, false, false}, + {true, false, false, false}, + {false, false, false, false}, + {false, false, false, false}, + }) + + n.processTimestamps(vids[0], genTimestamp(vids, []int{5, 1, 2, 2})) + s.checkTimeDiff(vids, n.timeDiffs[vids[0]], [][]int{ + {5, 1, 2, 2}, + {1, 1, 1, 0}, + {3, 1, 2, 1}, + {5, 1, 2, 2}, + }) + s.checkLastVotes(vids, n.lastVotes, [][]bool{ + {false, false, false, false}, + {true, false, false, false}, + {false, false, false, false}, + {false, false, false, false}, + }) +} + +func (s *NegativeAckTest) TestRestrictBySelf() { + var exist bool + n, vids := genTestNegativeAck(4) + n.setTimeDelay(timeDelay) + n.setTimeExpire(timeExpire) + + n.processTimestamps(vids[0], genTimestamp(vids, []int{1, 1, 1, 0})) + _, exist = n.getRestrictedValidators()[vids[1]] + s.Require().False(exist) + + n.processTimestamps(vids[0], genTimestamp(vids, []int{3, 1, 2, 1})) + _, exist = n.getRestrictedValidators()[vids[1]] + s.Require().True(exist) +} + +func (s *NegativeAckTest) TestRestrictByVoting() { + var nackeds []types.ValidatorID + var exist bool + + n, vids := genTestNegativeAck(4) + n.setTimeDelay(timeDelay) + n.setTimeExpire(timeExpire) + + n.processTimestamps(vids[0], genTimestamp(vids, []int{1, 1, 1, 1})) + n.processTimestamps(vids[0], genTimestamp(vids, []int{2, 2, 2, 2})) + + n.processTimestamps(vids[1], genTimestamp(vids, []int{1, 1, 1, 1})) + n.processTimestamps(vids[2], genTimestamp(vids, []int{1, 1, 1, 1})) + n.processTimestamps(vids[3], genTimestamp(vids, []int{1, 1, 1, 1})) + + nackeds = n.processTimestamps(vids[1], genTimestamp(vids, []int{1, 3, 3, 3})) + _, exist = n.getRestrictedValidators()[vids[0]] + s.Require().False(exist) + s.Require().Equal(0, len(nackeds)) + + nackeds = n.processTimestamps(vids[2], genTimestamp(vids, []int{1, 3, 3, 3})) + _, exist = n.getRestrictedValidators()[vids[0]] + s.Require().True(exist) + s.Require().Equal(0, len(nackeds)) + + nackeds = n.processTimestamps(vids[3], genTimestamp(vids, []int{1, 3, 3, 3})) + _, exist = n.getRestrictedValidators()[vids[0]] + s.Require().False(exist) + s.Require().Equal(1, len(nackeds)) + s.Require().Equal(vids[0], nackeds[0]) +} + +func (s *NegativeAckTest) TestExpire() { + var exist bool + + n, vids := genTestNegativeAck(4) + n.setTimeDelay(timeDelay) + n.setTimeExpire(timeExpire) + + n.processTimestamps(vids[0], genTimestamp(vids, []int{1, 1, 1, 1})) + n.processTimestamps(vids[1], genTimestamp(vids, []int{1, 1, 1, 1})) + n.processTimestamps(vids[2], genTimestamp(vids, []int{1, 1, 1, 1})) + n.processTimestamps(vids[3], genTimestamp(vids, []int{1, 1, 1, 1})) + + n.processTimestamps(vids[1], genTimestamp(vids, []int{1, 3, 3, 3})) + n.processTimestamps(vids[2], genTimestamp(vids, []int{1, 3, 3, 3})) + _, exist = n.getRestrictedValidators()[vids[0]] + s.Require().True(exist) + + time.Sleep(2 * timeExpire) + + n.processTimestamps(vids[0], genTimestamp(vids, []int{2, 2, 2, 2})) + + _, exist = n.getRestrictedValidators()[vids[0]] + s.Require().False(exist) +} + +func (s *NegativeAckTest) TestAddDeleteValidator() { + n, vids := genTestNegativeAck(10) + s.Require().Equal(10, len(n.timeDiffs)) + s.Require().Equal(10, len(n.timeDiffs[vids[0]])) + + for _, vid := range vids { + n.deleteValidator(vid) + } + s.Require().Equal(0, len(n.timeDiffs)) +} + +func TestNegativeAck(t *testing.T) { + suite.Run(t, new(NegativeAckTest)) +} -- cgit v1.2.3