SolanaのAnchorで、結合テスト、システムテストとテストファイルを分けて、個別にテスト実行したときに発生した現象。
Agenda
前提
個別テストする前に、solana-test-validatorでローカルのバリデーターは起動済みの状態:
% solana-test-validator
--faucet-sol argument ignored, ledger already exists
Ledger location: test-ledger
Log: test-ledger/validator.log
⠈ Initializing...
Identity: CYVZukfTPo9MnTob8zQ5ZraMr9n1rfy65BorMiLLogSY
Genesis Hash: 79Mmdu3eybVNJcQVhSDfNrvdSNAxNQmWLoztcRJ7paSM
Version: 1.14.10
Shred Version: 61746
Gossip Address: 127.0.0.1:1024
TPU Address: 127.0.0.1:1027
JSON RPC URL: http://127.0.0.1:8899
⠒ 00:25:19 | Processed Slot: 11244 | Confirmed Slot: 11244 | Finalized Slot: 11212 | Full Snapshot Slot: 11202 | Incremental Snapshot Slot: - | Transactions: 11893 | ◎499.945462500
Anchor.toml:
[features]
seeds = false
skip-lint = false
[programs.localnet]
hok = "CTgTMTJ2jkCU2TKkWa7FNiLa8aEcsu1knKPahSN9tLD"
[registry]
url = "https://api.apr.dev"
[provider]
cluster = "Localnet"
wallet = "~/.config/solana/id.json"
[scripts]
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
system-test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/system.ts"
↑個別実行できるように、最終行に system-test を追記している。
ファイル構成(テストファイルの場所のみ):
tests/integration.ts
tests/system.ts ← 「anchor run system-test」でこれを実行するようにしている
現象
個別テストを実行すると以下のエラー。
% anchor run system-test
yarn run v1.22.10
warning package.json: No license field
$ /Users/user/Documents/Programming/exit-cafe/Hibernation-of-KUMA/programs/node_modules/.bin/ts-mocha -p ./tsconfig.json -t 1000000 tests/system.ts
HoK System Test
1) Airdrop SOL to Users
Success for new record.
undefined
✔ Create event by Provider
1 passing (124ms)
1 failing
1) HoK System Test
Airdrop SOL to Users:
Error: failed to get recent blockhash: FetchError: request to http://localhost:8899/ failed, reason: connect ECONNREFUSED ::1:8899
at Connection.getLatestBlockhash (node_modules/@solana/web3.js/src/connection.ts:4498:13)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
原因
ローカルのバリデーターとURLが異なるため。
ローカルバリデーター:http://127.0.0.1:8899
Anchorが指定したバリデーター:http://localhost:8899/
対応
Anchor.tomlを以下に修正すると、127.0.0.1を指定するようになる。
[provider]
# cluster = "Localnet" # コメントアウト
cluster = "http://127.0.0.1:8899" # 追記
wallet = "~/.config/solana/id.json"
備考
solana-test-validator側の設定変更でも対応できそうな気がしたが、URL指定がうまくいかず断念した。
【追記】
ターミナル上で、solana-test-validatorコマンドで設定を試行錯誤していたが、anchor testで利用するsolana-test-validatorは、おそらく以下で設定が可能と思われる。
試してないが、以下を設定変更することで解決される可能性あり。
[test.validator]
url = "https://api.mainnet-beta.solana.com" # This is the url of the cluster that accounts are cloned from (See `test.validator.clone`).
warp_slot = 1337 # Warp the ledger to `warp_slot` after starting the validator.
slots_per_epoch = 5 # Override the number of slots in an epoch.
rpc_port = 1337 # Set JSON RPC on this port, and the next port for the RPC websocket.
limit_ledger_size = 1337 # Keep this amount of shreds in root slots.
ledger = "test-ledger" # Set ledger location.
gossip_port = 1337 # Gossip port number for the validator.
gossip_host = "127.0.0.1" # Gossip DNS name or IP address for the validator to advertise in gossip.
faucet_sol = 1337 # Give the faucet address this much SOL in genesis.
faucet_port = 1337 # Enable the faucet on this port.
dynamic_port_range = "1337 - 13337" # Range to use for dynamically assigned ports.
bind_address = "0.0.0.0" # IP address to bind the validator ports.
test.validator.clone
補足
Solanaのprogram(sendAndConfirmTransactionなど)は、本対応でうまくいったが、Anchorで作ったprogram(AnchorでRust開発)したものだと、うまく動かないケースが発生した。
そのときは、nodeのバージョンをv18からv16にダウングレードすることでうまくいった。
おそらく、これが正規の解決方法っぽい。
AnchorのIssuesを見ると、Solana本体のsolana-test-validatorが原因と書かれている。