Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,29 @@ jobs:
make linter
make

# 全量 go test -race 单 job 约 13 分钟,拆成 4 个并行分片执行;
# 聚合 job 仍命名为 unit-test,保持分支保护里 Required check 的名称不变。
unit-test:
name: unit-test
needs: unit-test-shard
if: always()
runs-on: ubuntu-22.04
steps:
- name: check shards
run: |
echo "shards result: ${{ needs.unit-test-shard.result }}"
if [ "${{ needs.unit-test-shard.result }}" != "success" ]; then
echo "::error::unit-test 分片未全部通过"
exit 1
fi

unit-test-shard:
name: unit-test shard
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
shard: [1, 2, 3, 4]
steps:
- name: checkout
uses: actions/checkout@v4
Expand All @@ -49,7 +69,11 @@ jobs:
- name: set go env
run: export PATH=${PATH}:`go env GOPATH`/bin
- name: unit-test
run: make test
run: |
# 按包序号取模分片,不维护硬编码包列表,新增包会自动落到某个分片
PKGS=$(go list ./... | grep -v pbft | awk -v s=${{ matrix.shard }} 'NR % 4 == s % 4')
echo "shard ${{ matrix.shard }}: $(echo "$PKGS" | wc -l) packages"
go test -parallel=8 -race $PKGS

coverage:
name: coverage
Expand Down
20 changes: 14 additions & 6 deletions plugin/dapp/paracross/testnode/paranode.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,25 @@ func NewParaNode(main *testnode.Chain33Mock, para *testnode.Chain33Mock) *ParaNo
main.Listen()
}
if para == nil {
cfg := types.NewChain33Config(DefaultConfig)
cfg.GetModuleConfig().RPC.ParaChain.MainChainGrpcAddr = main.GetCfg().RPC.GrpcBindAddr
para = testnode.NewWithConfig(cfg, nil)
// chain33 ForkParaFee 默认-1,测试模式 SetAllFork(0) 激活收费
// 导致 para 链处理同步区块时收手续费破坏共识,手动覆盖
para.GetClient().GetConfig().SetFork("ForkParaFee", types.MaxHeight)
para = testnode.NewWithConfig(newParaConfig(main.GetCfg().RPC.GrpcBindAddr), nil)
para.Listen()
}
return &ParaNode{Main: main, Para: para}
}

// newParaConfig 构造平行链节点配置。对配置的所有写入(尤其是 Forks)都必须在创建节点之前完成:
// testnode.NewWithConfig 会立即启动 blockchain 等后台 goroutine 并并发读取 Forks
// (Block.Hash() -> cfg.IsFork()),而 chain33 的 Forks 没有锁,
// 之后再写 Forks 会构成数据竞争,在 -race 下表现为 TestParaNode 随机失败。
func newParaConfig(mainGrpcAddr string) *types.Chain33Config {
cfg := types.NewChain33Config(DefaultConfig)
cfg.GetModuleConfig().RPC.ParaChain.MainChainGrpcAddr = mainGrpcAddr
// chain33 ForkParaFee 默认-1,测试模式 SetAllFork(0) 激活收费,
// 导致 para 链处理同步区块时收手续费破坏共识,这里覆盖为禁用。
cfg.SetFork("ForkParaFee", types.MaxHeight)
return cfg
}

// Close 关闭系统
func (node *ParaNode) Close() {
node.Para.Close()
Expand Down
24 changes: 24 additions & 0 deletions plugin/dapp/paracross/testnode/paranode_fork_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package testnode

import (
"testing"

"github.com/33cn/chain33/types"
"github.com/stretchr/testify/assert"
)

// TestNewParaConfigDisablesForkParaFee 固化 newParaConfig 的约定:
// ForkParaFee 必须在**创建节点之前**被置为 MaxHeight(禁用)。原因有两条:
// 1. 测试模式下 chain33 会把所有 fork 置 0,导致 para 链收手续费破坏共识;
// 2. testnode.NewWithConfig 会立即启动 blockchain 等后台 goroutine 并发读取 Forks,
// 之后再写 Forks 会构成数据竞争(chain33 的 Forks 无锁),
// 在 -race 下表现为 TestParaNode 随机失败。
//
// 这里刻意不启动节点:断言配置本身即可,避免测试自身的启停时序引入新的不稳定。
func TestNewParaConfigDisablesForkParaFee(t *testing.T) {
cfg := newParaConfig("127.0.0.1:0")

assert.False(t, cfg.IsFork(0, "ForkParaFee"), "ForkParaFee 应保持禁用")
assert.Equal(t, int64(types.MaxHeight), cfg.GetFork("ForkParaFee"))
assert.Equal(t, "127.0.0.1:0", cfg.GetModuleConfig().RPC.ParaChain.MainChainGrpcAddr)
}
Loading