Program Testi

Go'dan özel bir Solana programını test etmek, derlenmiş .so dosyasını SVM'ye yüklemek, programın beklediği hesapları ayarlamak ve programa karşı talimatlar göndermek anlamına gelir. litesvm-go tüm bunları işlem içinde gerçekleştirir - validator gerekmez.

Program Yükleme

package mytest
import (
"os"
"testing"
litesvm "github.com/LiteSVM/litesvm-go"
solana "github.com/gagliardetto/solana-go"
)
func TestLoadProgram(t *testing.T) {
svm, err := litesvm.New()
if err != nil {
t.Fatal(err)
}
defer svm.Close()
// Configure for program testing. Setters are infallible in practice;
// discarding the return keeps the example readable.
_ = svm.SetSigverify(false)
_ = svm.SetBlockhashCheck(false)
_ = svm.SetSysvars()
_ = svm.SetBuiltins()
// Load program from .so file.
programID := solana.NewWallet().PublicKey()
soPath := "./target/deploy/my_program.so"
if _, err := os.Stat(soPath); err != nil {
t.Skipf("program file not found: %s (build with: cargo build-sbf)", soPath)
}
if err := svm.AddProgramFromFile(programID, soPath); err != nil {
t.Fatal(err)
}
t.Logf("program loaded: %s", programID)
// Verify the program account.
acct := svm.GetAccount(programID)
if acct == nil {
t.Fatal("program account missing after load")
}
defer acct.Close()
t.Logf(" executable: %v", acct.Executable())
t.Logf(" data size: %d bytes", len(acct.Data()))
}

Eksiksiz Program Test Kurulumu

package mytest
import (
"os"
"testing"
litesvm "github.com/LiteSVM/litesvm-go"
solana "github.com/gagliardetto/solana-go"
)
func TestProgramEndToEnd(t *testing.T) {
svm, err := litesvm.New()
if err != nil {
t.Fatal(err)
}
defer svm.Close()
// Wide-open config: faster tests, less plumbing. Setters are infallible
// in practice; discarding the return keeps the example readable.
_ = svm.SetSigverify(false)
_ = svm.SetBlockhashCheck(false)
_ = svm.SetSysvars()
_ = svm.SetBuiltins()
_ = svm.SetPrecompiles()
_ = svm.SetTransactionHistory(100)
// Load the program.
programID := solana.NewWallet().PublicKey()
soPath := "./target/deploy/my_program.so"
if _, err := os.Stat(soPath); err != nil {
t.Skipf("missing %s", soPath)
}
if err := svm.AddProgramFromFile(programID, soPath); err != nil {
t.Fatal(err)
}
// Seed any data accounts the program expects.
dataAddr := solana.NewWallet().PublicKey()
dataPayload := make([]byte, 100)
rent, err := svm.MinimumBalanceForRentExemption(len(dataPayload))
if err != nil {
t.Fatal(err)
}
acct, err := litesvm.NewAccount(rent, dataPayload, programID, false, 0)
if err != nil {
t.Fatal(err)
}
defer acct.Close()
if err := svm.SetAccount(dataAddr, acct); err != nil {
t.Fatal(err)
}
// Fund a payer that will sign the test instruction.
priv, err := solana.NewRandomPrivateKey()
if err != nil {
t.Fatal(err)
}
payer := priv.PublicKey()
if err := svm.Airdrop(payer, 1_000_000_000); err != nil {
t.Fatal(err)
}
// Build an instruction against the program.
bh, err := svm.LatestBlockhash()
if err != nil {
t.Fatal(err)
}
ix := &solana.GenericInstruction{
ProgID: programID,
AccountValues: solana.AccountMetaSlice{
{PublicKey: dataAddr, IsWritable: true, IsSigner: false},
{PublicKey: payer, IsWritable: true, IsSigner: true},
},
DataBytes: []byte{0x01 /* discriminator + args */},
}
tx, err := solana.NewTransaction(
[]solana.Instruction{ix},
bh,
solana.TransactionPayer(payer),
)
if err != nil {
t.Fatal(err)
}
if _, err := tx.Sign(func(k solana.PublicKey) *solana.PrivateKey {
if k.Equals(payer) {
return &priv
}
return nil
}); err != nil {
t.Fatal(err)
}
txBytes, err := tx.MarshalBinary()
if err != nil {
t.Fatal(err)
}
// Execute and inspect.
out, err := svm.SendLegacyTransaction(txBytes)
if err != nil {
t.Fatal(err)
}
defer out.Close()
if !out.IsOk() {
t.Fatalf("program failed: %s\nlogs: %v", out.Error(), out.Logs())
}
t.Logf("logs: %v", out.Logs())
t.Logf("compute: %d CU", out.ComputeUnits())
// Verify state changes by reading the data account back.
updated := svm.GetAccount(dataAddr)
if updated == nil {
t.Fatal("data account missing after execution")
}
defer updated.Close()
// Decode `updated.Data()` and assert as needed.
}

Varsayılan Programları Kullanma

Standart programlara (SPL Token, Memo, ...) ihtiyaç duyan testler için:

svm, err := litesvm.New()
if err != nil {
t.Fatal(err)
}
defer svm.Close()
if err := svm.SetDefaultPrograms(); err != nil { // SPL Token, Memo, etc.
t.Fatal(err)
}
if err := svm.WithNativeMints(); err != nil { // wrapped-SOL mint
t.Fatal(err)
}

.so dosyasını oluşturmak için Solana programınızı cargo build-sbf ile derleyin.

Kalıp her zaman aynıdır:

  1. Yapılandırma - gerektiğinde sysvar'ları, yerleşikleri ve ön derleme bileşenlerini etkinleştirin.
  2. Program yükleme - AddProgramFromFile (veya bellek içi baytlar için AddProgram).
  3. Hesap kurulumu - veri hesaplarını SetAccount ile önceden doldurun.
  4. Gönderme - solana-go ile talimatı oluşturun, serileştirin ve SendLegacyTransaction aracılığıyla gönderin.
  5. Doğrulama - hesapları GetAccount ile geri okuyun ve günlükler, hesaplama birimleri ve son durum üzerinde doğrulama yapın.

Bu iskelet çalışır hale geldiğinde, daha fazla talimat, daha fazla hesap ve standart kod için bir yardımcı ekleyerek ölçeği büyütün.

Is this page helpful?

İçindekiler

Sayfayı Düzenle
© 2026 Solana Vakfı. Tüm hakları saklıdır.