Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
G
Goshimmer_without_tipselection
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
COLLET Ismael
Goshimmer_without_tipselection
Commits
c4e7c5c5
Unverified
Commit
c4e7c5c5
authored
4 years ago
by
jonastheis
Browse files
Options
Downloads
Patches
Plain Diff
Add unit tests
parent
a85eaf06
Branches
Branches containing commit
Tags
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
dapps/valuetransfers/packages/tipmanager/tipmanager.go
+17
-7
17 additions, 7 deletions
dapps/valuetransfers/packages/tipmanager/tipmanager.go
dapps/valuetransfers/packages/tipmanager/tipmanager_test.go
+175
-51
175 additions, 51 deletions
dapps/valuetransfers/packages/tipmanager/tipmanager_test.go
with
192 additions
and
58 deletions
dapps/valuetransfers/packages/tipmanager/tipmanager.go
+
17
−
7
View file @
c4e7c5c5
...
...
@@ -67,10 +67,16 @@ func newBranch(branchID branchmanager.BranchID, liked bool) *Branch {
}
}
// LikableBrancher defines an interface for a likable branch.
type
LikableBrancher
interface
{
ID
()
branchmanager
.
BranchID
Liked
()
bool
}
// AddTip adds the given value object as a tip in the given branch.
// If the branch is liked it is also added to t.tips.
// Parents are handled depending on the relation (same or different branch).
func
(
t
*
TipManager
)
AddTip
(
valueObject
*
payload
.
Payload
,
b
*
branchmanager
.
Branch
)
{
func
(
t
*
TipManager
)
AddTip
(
valueObject
*
payload
.
Payload
,
b
Likable
Branch
er
)
{
t
.
mutex
.
Lock
()
defer
t
.
mutex
.
Unlock
()
...
...
@@ -115,17 +121,17 @@ func (t *TipManager) Tips() (parent1ObjectID, parent2ObjectID payload.ID) {
return
}
parent1ObjectID
=
tip
.
(
Tip
)
.
id
parent1ObjectID
=
tip
.
(
*
Tip
)
.
id
if
t
.
tips
.
Size
()
==
1
{
parent2ObjectID
=
parent1ObjectID
return
}
parent2ObjectID
=
t
.
tips
.
RandomEntry
()
.
(
Tip
)
.
id
parent2ObjectID
=
t
.
tips
.
RandomEntry
()
.
(
*
Tip
)
.
id
// select 2 distinct tips if there's more than 1 tip available
for
parent1ObjectID
==
parent2ObjectID
&&
t
.
tips
.
Size
()
>
1
{
parent2ObjectID
=
t
.
tips
.
RandomEntry
()
.
(
Tip
)
.
id
parent2ObjectID
=
t
.
tips
.
RandomEntry
()
.
(
*
Tip
)
.
id
}
return
...
...
@@ -155,7 +161,7 @@ func (t *TipManager) OnBranchLiked(branchID branchmanager.BranchID) {
}
// remove tips from referenced branches
for
objectID
,
_
:=
range
branch
.
entryPoints
{
for
objectID
:=
range
branch
.
entryPoints
{
t
.
tips
.
Delete
(
objectID
)
}
}
...
...
@@ -180,7 +186,7 @@ func (t *TipManager) OnBranchDisliked(branchID branchmanager.BranchID) {
}
}
// OnBranch
Dislik
ed is called when a branch is merged.
// OnBranch
Merg
ed is called when a branch is merged.
// TODO: it should perform some cleanup logic
func
(
t
*
TipManager
)
OnBranchMerged
(
branchID
branchmanager
.
BranchID
)
{
// remove all tips from t.tips
...
...
@@ -198,7 +204,11 @@ func removeTipAsEntryPoint(tip *Tip) {
// If the parent is in the same branch it is removed as a tip.
// If the parent is not in the same branch a two-way mapping from parent to branch and branch to parent is created.
func
addTipHandleParent
(
parentID
payload
.
ID
,
parentBranch
*
Branch
,
branch
*
Branch
)
{
parentTip
:=
parentBranch
.
tips
[
parentID
]
parentTip
,
ok
:=
parentBranch
.
tips
[
parentID
]
// parent is not a tip anymore
if
!
ok
{
return
}
if
parentBranch
.
branchID
==
branch
.
branchID
{
// remove parents out of branch.tips
...
...
This diff is collapsed.
Click to expand it.
dapps/valuetransfers/packages/tipmanager/tipmanager_test.go
+
175
−
51
View file @
c4e7c5c5
package
tipmanager
import
(
"sync"
"testing"
"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/address"
"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/balance"
"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/branchmanager"
"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/payload"
"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/transaction"
"github.com/stretchr/testify/assert"
)
/*
func
TestTipManagerSimple
(
t
*
testing
.
T
)
{
tipManager
:=
New
()
...
...
@@ -15,74 +20,193 @@ func TestTipManagerSimple(t *testing.T) {
assert
.
Equal
(
t
,
payload
.
GenesisID
,
parent1
)
assert
.
Equal
(
t
,
payload
.
GenesisID
,
parent2
)
// add few tips and check whether total tips count matches
totalTips := 100
branchesMap := make(map[branchmanager.BranchID]*payload.Payload, totalTips)
branches := make([]branchmanager.BranchID, totalTips)
for i := 0; i < totalTips; i++ {
branchID := branchmanager.NewBranchID(transaction.RandomID())
branches[i] = branchID
branchesMap[branchID] = payload.New(payload.GenesisID, payload.GenesisID, createDummyTransaction())
tipManager.AddTip(branchesMap[branchID], branchID)
}
assert.Equal(t, totalTips, tipManager.TipCount(branches...))
// add 1 transaction in liked branch -> both tips need to point there
tx
:=
createDummyTransaction
()
branch1
:=
newMockBranch
(
tx
.
ID
(),
true
)
valueObject
:=
payload
.
New
(
payload
.
GenesisID
,
payload
.
GenesisID
,
tx
)
branch1
.
addTip
(
valueObject
)
tipManager
.
AddTip
(
valueObject
,
branch1
)
// check if tips point to genesis when branches are not found
parent1, parent2 = tipManager.Tips(branchmanager.UndefinedBranchID, branchmanager.NewBranchID(transaction.RandomID()))
assert.Equal(t, 0, tipManager.TipCount(branchmanager.UndefinedBranchID, branchmanager.NewBranchID(transaction.RandomID())))
assert.Equal(t, payload.GenesisID, parent1)
assert.Equal(t, payload.GenesisID, parent2)
assert
.
Equal
(
t
,
1
,
tipManager
.
TipCount
())
parent1
,
parent2
=
tipManager
.
Tips
()
assert
.
Equal
(
t
,
valueObject
.
ID
(),
parent1
)
assert
.
Equal
(
t
,
valueObject
.
ID
(),
parent2
)
// use each branch to get the single tip
for b, o := range branchesMap {
parent1ObjectID, parent2ObjectID := tipManager.Tips(b)
assert.Equal(t, o.ID(), parent1ObjectID)
assert.Equal(t, o.ID(), parent2ObjectID)
}
// add a bunch of liked tips -> check count
numTips
:=
10
branch2
:=
newMockBranch
(
transaction
.
RandomID
(),
true
)
for
i
:=
0
;
i
<
numTips
;
i
++
{
v
:=
payload
.
New
(
payload
.
GenesisID
,
payload
.
GenesisID
,
createDummyTransaction
())
branch1
.
addTip
(
v
)
tipManager
.
AddTip
(
v
,
branch1
)
// select tips from two branches
parent1, parent2 = tipManager.Tips(branches[0], branches[1])
s := []payload.ID{
branchesMap[branches[0]].ID(),
branchesMap[branches[1]].ID(),
v
=
payload
.
New
(
payload
.
GenesisID
,
payload
.
GenesisID
,
createDummyTransaction
())
branch2
.
addTip
(
v
)
tipManager
.
AddTip
(
v
,
branch2
)
}
assert.Contains(t, s, parent1)
assert.Contains(t, s, parent2)
}
func TestTipManagerParallel(t *testing.T) {
totalTips := 1000
totalThreads := 100
totalBranches := 10
assert
.
Equal
(
t
,
branch1
.
tipCount
()
+
branch2
.
tipCount
(),
tipManager
.
TipCount
())
assert
.
Equal
(
t
,
branch1
.
tipCount
(),
len
(
tipManager
.
branches
[
branch1
.
ID
()]
.
tips
))
assert
.
Equal
(
t
,
branch2
.
tipCount
(),
len
(
tipManager
.
branches
[
branch2
.
ID
()]
.
tips
))
parent1
,
parent2
=
tipManager
.
Tips
()
assert
.
NotEqual
(
t
,
parent1
,
parent2
)
tipManager := New()
// add a bunch of disliked tips -> count should be unchanged
branch3
:=
newMockBranch
(
transaction
.
RandomID
(),
false
)
branch4
:=
newMockBranch
(
transaction
.
RandomID
(),
false
)
for
i
:=
0
;
i
<
numTips
;
i
++
{
v
:=
payload
.
New
(
payload
.
GenesisID
,
payload
.
GenesisID
,
createDummyTransaction
())
branch3
.
addTip
(
v
)
tipManager
.
AddTip
(
v
,
branch3
)
branches := make([]branchmanager.BranchID, totalBranches)
for i := 0; i < totalBranches; i++ {
branchID := branchmanager.NewBranchID(transaction.RandomID())
branches[i] = branchID
v
=
payload
.
New
(
payload
.
GenesisID
,
payload
.
GenesisID
,
createDummyTransaction
())
branch4
.
addTip
(
v
)
tipManager
.
AddTip
(
v
,
branch4
)
}
// add tips in parallel
assert
.
Equal
(
t
,
branch1
.
tipCount
()
+
branch2
.
tipCount
(),
tipManager
.
TipCount
())
assert
.
Equal
(
t
,
branch1
.
tipCount
(),
len
(
tipManager
.
branches
[
branch1
.
ID
()]
.
tips
))
assert
.
Equal
(
t
,
branch2
.
tipCount
(),
len
(
tipManager
.
branches
[
branch2
.
ID
()]
.
tips
))
assert
.
Equal
(
t
,
branch3
.
tipCount
(),
len
(
tipManager
.
branches
[
branch3
.
ID
()]
.
tips
))
assert
.
Equal
(
t
,
branch4
.
tipCount
(),
len
(
tipManager
.
branches
[
branch4
.
ID
()]
.
tips
))
// add tip to liked branch with parents from same branch -> should be in tipmanager.tips and parents removed from tipmanager.tips and branch's tips
removedTip1
:=
branch1
.
tip
()
removedTip2
:=
branch1
.
tip
()
valueObject
=
payload
.
New
(
removedTip1
,
removedTip2
,
createDummyTransaction
())
branch1
.
addTip
(
valueObject
)
tipManager
.
AddTip
(
valueObject
,
branch1
)
assert
.
Equal
(
t
,
branch1
.
tipCount
()
+
branch2
.
tipCount
(),
tipManager
.
TipCount
())
_
,
ok
:=
tipManager
.
tips
.
Get
(
removedTip1
)
assert
.
False
(
t
,
ok
)
_
,
ok
=
tipManager
.
tips
.
Get
(
removedTip2
)
assert
.
False
(
t
,
ok
)
_
,
ok
=
tipManager
.
tips
.
Get
(
valueObject
.
ID
())
assert
.
True
(
t
,
ok
)
_
,
ok
=
tipManager
.
branches
[
branch1
.
ID
()]
.
tips
[
removedTip1
]
assert
.
False
(
t
,
ok
)
_
,
ok
=
tipManager
.
branches
[
branch1
.
ID
()]
.
tips
[
removedTip2
]
assert
.
False
(
t
,
ok
)
_
,
ok
=
tipManager
.
branches
[
branch1
.
ID
()]
.
tips
[
valueObject
.
ID
()]
assert
.
True
(
t
,
ok
)
// add tip to disliked branch with parents from same branch -> tipmanager.tips should be unmodified, only branch's tips modified
removedTip1
=
branch3
.
tip
()
removedTip2
=
branch3
.
tip
()
valueObject
=
payload
.
New
(
removedTip1
,
removedTip2
,
createDummyTransaction
())
branch3
.
addTip
(
valueObject
)
tipManager
.
AddTip
(
valueObject
,
branch3
)
assert
.
Equal
(
t
,
branch1
.
tipCount
()
+
branch2
.
tipCount
(),
tipManager
.
TipCount
())
_
,
ok
=
tipManager
.
branches
[
branch3
.
ID
()]
.
tips
[
removedTip1
]
assert
.
False
(
t
,
ok
)
_
,
ok
=
tipManager
.
branches
[
branch3
.
ID
()]
.
tips
[
removedTip2
]
assert
.
False
(
t
,
ok
)
_
,
ok
=
tipManager
.
branches
[
branch3
.
ID
()]
.
tips
[
valueObject
.
ID
()]
assert
.
True
(
t
,
ok
)
}
// TestTipManagerParallel tests the TipManager's functionality by adding and selecting tips concurrently.
func
TestTipManagerConcurrent
(
t
*
testing
.
T
)
{
numThreads
:=
10
numTips
:=
100
branches
:=
make
([]
*
mockBranch
,
numThreads
)
tipManager
:=
New
()
var
wg
sync
.
WaitGroup
for i := 0; i < totalThreads; i++ {
// add tips to numThreads branches in parallel
for
i
:=
0
;
i
<
numThreads
;
i
++
{
wg
.
Add
(
1
)
go func() {
go
func
(
number
int
)
{
defer
wg
.
Done
()
for t := 0; t < totalTips; t++ {
tip := payload.New(payload.GenesisID, payload.GenesisID, createDummyTransaction())
random := rand.Intn(totalBranches)
tipManager.AddTip(tip, branches[random])
branch
:=
newMockBranch
(
transaction
.
RandomID
(),
number
<
numThreads
/
2
)
branches
[
number
]
=
branch
// add tips within a branch in parallel
var
wg2
sync
.
WaitGroup
for
t
:=
0
;
t
<
numTips
;
t
++
{
v
:=
payload
.
New
(
payload
.
GenesisID
,
payload
.
GenesisID
,
createDummyTransaction
())
branch
.
addTip
(
v
)
wg2
.
Add
(
1
)
go
func
()
{
defer
wg2
.
Done
()
tipManager
.
AddTip
(
v
,
branch
)
}()
}
}()
wg2
.
Wait
()
removedTip1
:=
branch
.
tip
()
removedTip2
:=
branch
.
tip
()
valueObject
:=
payload
.
New
(
removedTip1
,
removedTip2
,
createDummyTransaction
())
branch
.
addTip
(
valueObject
)
tipManager
.
AddTip
(
valueObject
,
branch
)
}(
i
)
}
wg
.
Wait
()
// check total tip count
assert.Equal(t, totalTips*totalThreads, tipManager.TipCount(branches...))
// verify tips of every branch
for
i
:=
0
;
i
<
numThreads
;
i
++
{
branch
:=
branches
[
i
]
assert
.
Equal
(
t
,
branch
.
tipCount
(),
len
(
tipManager
.
branches
[
branch
.
ID
()]
.
tips
))
for
tip
:=
range
branch
.
tips
{
// all tips should be in branch's list
_
,
ok
:=
tipManager
.
branches
[
branch
.
ID
()]
.
tips
[
tip
]
assert
.
True
(
t
,
ok
)
// make sure that all tips from liked branches (and none from disliked branches) are in tipmanager.tips
_
,
ok
=
tipManager
.
tips
.
Get
(
tip
)
assert
.
Equal
(
t
,
branch
.
Liked
(),
ok
)
}
}
// total tips: numThreads/2 (liked branches) * numTips - numThreads/2 (selected tips)
assert
.
Equal
(
t
,
numThreads
/
2
*
numTips
-
numThreads
/
2
,
tipManager
.
TipCount
())
}
type
mockBranch
struct
{
id
branchmanager
.
BranchID
liked
bool
tips
map
[
payload
.
ID
]
payload
.
ID
}
func
newMockBranch
(
txID
transaction
.
ID
,
liked
bool
)
*
mockBranch
{
return
&
mockBranch
{
id
:
branchmanager
.
NewBranchID
(
txID
),
liked
:
liked
,
tips
:
make
(
map
[
payload
.
ID
]
payload
.
ID
),
}
}
func
(
m
*
mockBranch
)
ID
()
branchmanager
.
BranchID
{
return
m
.
id
}
func
(
m
*
mockBranch
)
Liked
()
bool
{
return
m
.
liked
}
func
(
m
*
mockBranch
)
addTip
(
valueObject
*
payload
.
Payload
)
{
m
.
tips
[
valueObject
.
ID
()]
=
valueObject
.
ID
()
}
func
(
m
*
mockBranch
)
tip
()
payload
.
ID
{
var
tip
payload
.
ID
// get some element
for
t
:=
range
m
.
tips
{
tip
=
t
}
delete
(
m
.
tips
,
tip
)
return
tip
}
func
(
m
*
mockBranch
)
tipCount
()
int
{
return
len
(
m
.
tips
)
}
*/
func
createDummyTransaction
()
*
transaction
.
Transaction
{
return
transaction
.
New
(
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment