unconfirmed_test 詳解
這是一個測試文件,主要用來測試 unconfirmed.go 中的相關功能。本篇需要先對 unconfirmed.go 文件中的源碼內容有一定的瞭解
還是按照老套路來解析(源碼從上到下)
當前源碼版本爲:1.9.0-unstable
//首先是 noopChainRetriever 空結構體的類型定義,在不增加多餘內存的目的下實現 unconfirmed.go 文件中 chainRetriever 接口。該接口中有兩個方法,如下。這兩個方法理論上應該是實現通過區塊高度返回對應的區塊頭和區塊功能。但是這裏爲了測試方便,就全返回了 nil 空值
type noopChainRetriever struct{}
func (r *noopChainRetriever) GetHeaderByNumber(number uint64) *types.Header {
return nil
}
func (r *noopChainRetriever) GetBlockByNumber(number uint64) *types.Block {
return nil
}
上圖對應下面 TestUnconfirmedInsertBounds 函數的處理流程
//手動插入若干 unconfirmed 區塊至 ring 環形鏈表中,直到環形鏈表中最老的 unconfirmed 區塊和待插入區塊之間的長度大於指定的 depth 長度。然後就將滿足條件的 unconfirmed 區塊從環形鏈表中刪掉
func TestUnconfirmedInsertBounds(t *testing.T) {
limit := uint(10) // depth 設置爲10,也就是說 unconfirmed 需要經過 10 個區塊的驗證纔可以進行刪除操作
pool := newUnconfirmedBlocks(new(noopChainRetriever), limit) //初始化 unconfirmedBlocks 數據結構
// 循環便利,從 1 - 10,都是往環形鏈表中插入 unconfirmed 區塊。從 11 開始,邊插入新的 unconfirmed 區塊邊刪除舊的 unconfirmed 區塊。
for depth := uint64(0); depth < 2*uint64(limit); depth++ {
// 每一個層級插入多個 unconfirmed 區塊。例如:i=1 時,插入一個 unconfirmed 區塊;i=2時,插入兩個 unconfirmed 區塊。以此累加。
for i := 0; i < int(depth); i++ {
pool.Insert(depth, common.Hash([32]byte{byte(depth), byte(i)})) //往環形鏈表中插入 unconfirmed 區塊。當然,插入的同時也會對滿足條件的舊的 unconfirmed 區塊進行刪除
}
// 驗證滿足 depth 長度要求的 unconfirmed 區塊是否已經被刪除。注意這裏傳入的是一個函數,結構有點特殊
pool.blocks.Do(func(block interface{}) {
if block := block.(*unconfirmedBlock); block.index+uint64(limit) <= depth {
t.Errorf("depth %d: block %x not dropped", depth, block.hash)
}
})
}
}
瞭解第一個測試函數之後第二個測試函數就顯的非常簡單了,這兒就不再貼流程圖。
//測試 shift 函數處理 unconfirmed 區塊的能力。含邊界測試
func TestUnconfirmedShifts(t *testing.T) {
// 設置 depth 長度爲 10.區塊號 從 25 開始
limit, start := uint(10), uint64(25)
//區塊號從 25 開始,往 pool 即環形鏈表中壓入 10 個 unconfirmed 區塊
pool := newUnconfirmedBlocks(new(noopChainRetriever), limit)
for depth := start; depth < start+uint64(limit); depth++ {
pool.Insert(depth, common.Hash([32]byte{byte(depth)}))
}
// 用 34 來測試 shift 方法對邊界值的處理
pool.Shift(start + uint64(limit) - 1)
if n := pool.blocks.Len(); n != int(limit) {
t.Errorf("unconfirmed count mismatch: have %d, want %d", n, limit)
}
// 測試移除掉一半 unconfirmed 區塊
pool.Shift(start + uint64(limit) - 1 + uint64(limit/2))
if n := pool.blocks.Len(); n != int(limit)/2 {
t.Errorf("unconfirmed count mismatch: have %d, want %d", n, limit/2)
}
// 測試移除掉所有剩下的 unconfirmed 區塊
pool.Shift(start + 2*uint64(limit))
if n := pool.blocks.Len(); n != 0 {
t.Errorf("unconfirmed count mismatch: have %d, want %d", n, 0)
}
// 測試 ring 環形鏈表爲空的情況下 Shift 方法對應 的處理能力
pool.Shift(start + 3*uint64(limit))
if n := pool.blocks.Len(); n != 0 {
t.Errorf("unconfirmed count mismatch: have %d, want %d", n, 0)
}
}