Menguji program Solana kustom dari Go berarti memuat file .so yang telah dikompilasi
ke dalam SVM, menyiapkan akun yang dibutuhkan, dan mengirimkan instruksi
kepadanya. litesvm-go menangani semua ini dalam proses - tidak perlu validator.
Memuat Program
package mytestimport ("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()))}
Pengaturan Uji Program Lengkap
package mytestimport ("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.}
Menggunakan Program Default
Untuk pengujian yang membutuhkan program standar (SPL Token, Memo, ...):
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 mintt.Fatal(err)}
Bangun program Solana Anda dengan cargo build-sbf untuk menghasilkan file .so.
Polanya selalu sama:
- Konfigurasi - aktifkan sysvars, builtins, precompiles sesuai kebutuhan.
- Pemuatan program -
AddProgramFromFile(atauAddProgramuntuk byte dalam memori). - Pengaturan akun - isi awal akun data dengan
SetAccount. - Pengiriman - bangun instruksi dengan
solana-go, marshal, kirimkan melaluiSendLegacyTransaction. - Verifikasi - baca kembali akun dengan
GetAccountdan periksa log, unit komputasi, dan status akhir.
Setelah kerangka ini berjalan, tingkatkan skala dengan menambahkan lebih banyak instruksi, lebih banyak akun, dan helper untuk kode boilerplate.
Is this page helpful?