Skip to content

Commit

Permalink
Merge branch 'governance' of https://github.com/gnoswap-labs/gnoswap
Browse files Browse the repository at this point in the history
…into governance
  • Loading branch information
onlyhyde committed Jan 3, 2025
2 parents a99503f + f80deca commit 372cb22
Show file tree
Hide file tree
Showing 3 changed files with 284 additions and 89 deletions.
84 changes: 84 additions & 0 deletions gov/staker/clean_delegation_stat_history_test.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package staker

import (
"std"
"testing"

"gno.land/p/demo/avl"
"gno.land/p/demo/testutils"
)

var (
testAddr1 = testutils.TestAddress("test1")
testAddr = testutils.TestAddress("test")
)

type mockEnv struct {
height uint64
isAdmin bool
}

func (m *mockEnv) GetHeight() int64 {
return int64(m.height)
}

func (m *mockEnv) IsAdmin() bool {
return m.isAdmin
}

func TestCleanDelegationStatHistory(t *testing.T) {
mock := &mockEnv{height: 1000, isAdmin: true}
std.TestSetOrigCaller(testAddr1)
delegationSnapShotHistory = avl.NewTree()

addr := testAddr.String()
history := []DelegationSnapShotHistory{
{updatedBlock: 500}, // Old
{updatedBlock: 900}, // Within threshold
{updatedBlock: 950}, // Latest
}
delegationSnapShotHistory.Set(addr, history)

tests := []struct {
name string
setupHeight uint64
lastCleaned uint64
threshold int64
expectedLen int
}{
{
name: "no clean needed",
setupHeight: 1000,
lastCleaned: 999,
threshold: 100,
expectedLen: 3,
},
{
name: "clean old records",
setupHeight: 1000,
lastCleaned: 800,
threshold: 100,
expectedLen: 3,
},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
mock.height = tc.setupHeight
lastCleanedHeight = tc.lastCleaned
thresholdVotingWeightBlockHeight = tc.threshold

cleanDelegationStatHistory()

value, exists := delegationSnapShotHistory.Get(addr)
if !exists {
t.Fatal("history should exist")
}

history := value.([]DelegationSnapShotHistory)
if len(history) != tc.expectedLen {
t.Errorf("expected history length %d, got %d", tc.expectedLen, len(history))
}
})
}
}
186 changes: 97 additions & 89 deletions gov/staker/delegate_undelegate_test.gno
Original file line number Diff line number Diff line change
Expand Up @@ -3,101 +3,109 @@ package staker
import (
"std"
"testing"
"time"

"gno.land/p/demo/avl"
"gno.land/p/demo/testutils"
)

func TestGetDelegatedCumulative(t *testing.T) {
delegationSnapShotHistory = avl.NewTree()

addr1 := testutils.TestAddress("test1")
now := uint64(time.Now().Unix())

tests := []struct {
name string
setupHistory []DelegationSnapShotHistory
delegator std.Address
endTimestamp uint64
expectAmount uint64
expectPanic bool
}{
{
name: "no history returns zero",
delegator: addr1,
endTimestamp: now,
expectAmount: 0,
},
{
name: "single history before timestamp",
setupHistory: []DelegationSnapShotHistory{
{
to: addr1,
amount: 100,
updatedBlock: 1,
updatedAt: now - 100,
},
},
delegator: addr1,
endTimestamp: now,
expectAmount: 100,
},
{
name: "multiple histories returns latest before timestamp",
setupHistory: []DelegationSnapShotHistory{
{
to: addr1,
amount: 100,
updatedBlock: 1,
updatedAt: now - 200,
},
{
to: addr1,
amount: 150,
updatedBlock: 2,
updatedAt: now - 100,
},
{
to: addr1,
amount: 200,
updatedBlock: 3,
updatedAt: now + 100, // Future update
},
},
delegator: addr1,
endTimestamp: now,
expectAmount: 150,
},
{
name: "future timestamp panics",
delegator: addr1,
endTimestamp: now + 1000,
expectPanic: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
delegationSnapShotHistory = avl.NewTree()

if len(tt.setupHistory) > 0 {
delegationSnapShotHistory.Set(tt.delegator.String(), tt.setupHistory)
}
func TestDelegate(t *testing.T) {
t.Skip("Must running separately. because this test depends on TestUndelegate's state")
std.TestSetOrigCaller(testAddr1)
resetState()

addr1 := testAddr1

t.Run("success - first delegation", func(t *testing.T) {
delegate(addr1, 100)

if totalDelegated != 100 {
t.Errorf("expected totalDelegated 100, got %d", totalDelegated)
}

value, exists := delegatorAmount.Get(addr1.String())
if !exists || value.(uint64) != 100 {
t.Error("delegator amount not updated correctly")
}

innerTree, exists := delegatedFromTo.Get(addr1.String())
if !exists {
t.Error("delegatedFromTo not updated")
}

inner := innerTree.(*avl.Tree)
delegatedAmount, exists := inner.Get(addr1.String())
if !exists {
t.Error("delegatedFromTo amount incorrect")
}

if delegatedAmount.(uint64) != 100 {
t.Error("delegatedFromTo amount incorrect")
}
})

t.Run("success - additional delegation", func(t *testing.T) {
resetState()
delegate(addr1, 100)
delegate(addr1, 50)

if tt.expectPanic {
defer func() {
if r := recover(); r == nil {
t.Errorf("expected panic but got none")
}
}()
if totalDelegated != 150 {
t.Errorf("expected totalDelegated 150, got %d", totalDelegated)
}
})
}

func TestUndelegate(t *testing.T) {
t.Skip("Must running separately. because this test depends on TestUndelegate's state")
addr1 := testAddr1
std.TestSetOrigCaller(addr1)
resetState()

t.Run("fail - no delegation", func(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Error("expected panic for no delegation")
}
}()
undelegate(addr1, 100)
})

t.Run("fail - insufficient amount", func(t *testing.T) {
delegate(addr1, 50)

result := GetDelegatedCumulative(tt.delegator, tt.endTimestamp)

if !tt.expectPanic && result != tt.expectAmount {
t.Errorf("expected amount %d but got %d", tt.expectAmount, result)
defer func() {
if r := recover(); r == nil {
t.Error("expected panic for insufficient amount")
}
})
}
}
}()
undelegate(addr1, 100)
})

t.Run("success - partial undelegate", func(t *testing.T) {
resetState()
delegate(addr1, 100)
undelegate(addr1, 30)

if totalDelegated != 70 {
t.Errorf("expected totalDelegated 70, got %d", totalDelegated)
}
})

t.Run("success - full undelegate", func(t *testing.T) {
resetState()
delegate(addr1, 100)
undelegate(addr1, 100)

if totalDelegated != 0 {
t.Errorf("expected totalDelegated 0, got %d", totalDelegated)
}
})
}

func resetState() {
totalDelegated = 0
delegatorAmount = avl.NewTree()
delegatedFromTo = avl.NewTree()
delegatedTo = avl.NewTree()
delegationHistory = avl.NewTree()
delegationSnapShotHistory = avl.NewTree()
}
103 changes: 103 additions & 0 deletions gov/staker/history_test.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package staker

import (
"std"
"testing"
"time"

"gno.land/p/demo/avl"
"gno.land/p/demo/testutils"
)

func TestGetDelegatedCumulative(t *testing.T) {
delegationSnapShotHistory = avl.NewTree()

addr1 := testutils.TestAddress("test1")
now := uint64(time.Now().Unix())

tests := []struct {
name string
setupHistory []DelegationSnapShotHistory
delegator std.Address
endTimestamp uint64
expectAmount uint64
expectPanic bool
}{
{
name: "no history returns zero",
delegator: addr1,
endTimestamp: now,
expectAmount: 0,
},
{
name: "single history before timestamp",
setupHistory: []DelegationSnapShotHistory{
{
to: addr1,
amount: 100,
updatedBlock: 1,
updatedAt: now - 100,
},
},
delegator: addr1,
endTimestamp: now,
expectAmount: 100,
},
{
name: "multiple histories returns latest before timestamp",
setupHistory: []DelegationSnapShotHistory{
{
to: addr1,
amount: 100,
updatedBlock: 1,
updatedAt: now - 200,
},
{
to: addr1,
amount: 150,
updatedBlock: 2,
updatedAt: now - 100,
},
{
to: addr1,
amount: 200,
updatedBlock: 3,
updatedAt: now + 100, // Future update
},
},
delegator: addr1,
endTimestamp: now,
expectAmount: 150,
},
{
name: "future timestamp panics",
delegator: addr1,
endTimestamp: now + 1000,
expectPanic: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
delegationSnapShotHistory = avl.NewTree()

if len(tt.setupHistory) > 0 {
delegationSnapShotHistory.Set(tt.delegator.String(), tt.setupHistory)
}

if tt.expectPanic {
defer func() {
if r := recover(); r == nil {
t.Errorf("expected panic but got none")
}
}()
}

result := GetDelegatedCumulative(tt.delegator, tt.endTimestamp)

if !tt.expectPanic && result != tt.expectAmount {
t.Errorf("expected amount %d but got %d", tt.expectAmount, result)
}
})
}
}

0 comments on commit 372cb22

Please sign in to comment.