github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/gnovm/tests/imports.go (about)

     1  package tests
     2  
     3  import (
     4  	"bufio"
     5  	"bytes"
     6  	"compress/flate"
     7  	"compress/gzip"
     8  	"context"
     9  	"crypto/md5" //nolint:gosec
    10  	crand "crypto/rand"
    11  	"crypto/sha1" //nolint:gosec
    12  	"encoding/base64"
    13  	"encoding/binary"
    14  	"encoding/json"
    15  	"encoding/xml"
    16  	"errors"
    17  	"flag"
    18  	"fmt"
    19  	"hash/fnv"
    20  	"image"
    21  	"image/color"
    22  	"io"
    23  	"log"
    24  	"math"
    25  	"math/big"
    26  	"math/rand"
    27  	"net"
    28  	"net/url"
    29  	"os"
    30  	"path/filepath"
    31  	"reflect"
    32  	"sort"
    33  	"strconv"
    34  	"strings"
    35  	"sync"
    36  	"sync/atomic"
    37  	"text/template"
    38  	"time"
    39  	"unicode/utf8"
    40  
    41  	gno "github.com/gnolang/gno/gnovm/pkg/gnolang"
    42  	"github.com/gnolang/gno/gnovm/stdlibs"
    43  	teststdlibs "github.com/gnolang/gno/gnovm/tests/stdlibs"
    44  	"github.com/gnolang/gno/tm2/pkg/db/memdb"
    45  	osm "github.com/gnolang/gno/tm2/pkg/os"
    46  	"github.com/gnolang/gno/tm2/pkg/std"
    47  	"github.com/gnolang/gno/tm2/pkg/store/dbadapter"
    48  	"github.com/gnolang/gno/tm2/pkg/store/iavl"
    49  	stypes "github.com/gnolang/gno/tm2/pkg/store/types"
    50  )
    51  
    52  type importMode uint64
    53  
    54  // Import modes to control the import behaviour of TestStore.
    55  const (
    56  	// use stdlibs/* only (except a few exceptions). for stdlibs/* and examples/* testing.
    57  	ImportModeStdlibsOnly importMode = iota
    58  	// use stdlibs/* if present, otherwise use native. used in files/tests, excluded for *_native.go
    59  	ImportModeStdlibsPreferred
    60  	// do not use stdlibs/* if native registered. used in files/tests, excluded for *_stdlibs.go
    61  	ImportModeNativePreferred
    62  )
    63  
    64  // NOTE: this isn't safe, should only be used for testing.
    65  func TestStore(rootDir, filesPath string, stdin io.Reader, stdout, stderr io.Writer, mode importMode) (store gno.Store) {
    66  	getPackage := func(pkgPath string, newStore gno.Store) (pn *gno.PackageNode, pv *gno.PackageValue) {
    67  		if pkgPath == "" {
    68  			panic(fmt.Sprintf("invalid zero package path in testStore().pkgGetter"))
    69  		}
    70  		if mode != ImportModeStdlibsOnly &&
    71  			mode != ImportModeStdlibsPreferred &&
    72  			mode != ImportModeNativePreferred {
    73  			panic(fmt.Sprintf("unrecognized import mode"))
    74  		}
    75  
    76  		if filesPath != "" {
    77  			// if _test package...
    78  			const testPath = "github.com/gnolang/gno/_test/"
    79  			if strings.HasPrefix(pkgPath, testPath) {
    80  				baseDir := filepath.Join(filesPath, "extern", pkgPath[len(testPath):])
    81  				memPkg := gno.ReadMemPackage(baseDir, pkgPath)
    82  				send := std.Coins{}
    83  				ctx := testContext(pkgPath, send)
    84  				m2 := gno.NewMachineWithOptions(gno.MachineOptions{
    85  					PkgPath: "test",
    86  					Output:  stdout,
    87  					Store:   newStore,
    88  					Context: ctx,
    89  				})
    90  				// pkg := gno.NewPackageNode(gno.Name(memPkg.Name), memPkg.Path, nil)
    91  				// pv := pkg.NewPackage()
    92  				// m2.SetActivePackage(pv)
    93  				return m2.RunMemPackage(memPkg, false)
    94  			}
    95  		}
    96  
    97  		// if stdlibs package is preferred , try to load it first.
    98  		if mode == ImportModeStdlibsOnly ||
    99  			mode == ImportModeStdlibsPreferred {
   100  			pn, pv = loadStdlib(rootDir, pkgPath, newStore, stdout)
   101  			if pn != nil {
   102  				return
   103  			}
   104  		}
   105  
   106  		// if native package is allowed, return it.
   107  		if pkgPath == "os" || // special cases even when StdlibsOnly (for tests).
   108  			pkgPath == "fmt" || // TODO: try to minimize these exceptions over time.
   109  			pkgPath == "log" ||
   110  			pkgPath == "crypto/rand" ||
   111  			pkgPath == "crypto/md5" ||
   112  			pkgPath == "crypto/sha1" ||
   113  			pkgPath == "encoding/binary" ||
   114  			pkgPath == "encoding/json" ||
   115  			pkgPath == "encoding/xml" ||
   116  			pkgPath == "internal/os_test" ||
   117  			pkgPath == "math/big" ||
   118  			pkgPath == "math/rand" ||
   119  			mode == ImportModeStdlibsPreferred ||
   120  			mode == ImportModeNativePreferred {
   121  			switch pkgPath {
   122  			case "os":
   123  				pkg := gno.NewPackageNode("os", pkgPath, nil)
   124  				pkg.DefineGoNativeValue("Stdin", stdin)
   125  				pkg.DefineGoNativeValue("Stdout", stdout)
   126  				pkg.DefineGoNativeValue("Stderr", stderr)
   127  				return pkg, pkg.NewPackage()
   128  			case "fmt":
   129  				pkg := gno.NewPackageNode("fmt", pkgPath, nil)
   130  				pkg.DefineGoNativeType(reflect.TypeOf((*fmt.Stringer)(nil)).Elem())
   131  				pkg.DefineGoNativeType(reflect.TypeOf((*fmt.Formatter)(nil)).Elem())
   132  				pkg.DefineGoNativeValue("Println", func(a ...interface{}) (n int, err error) {
   133  					// NOTE: uncomment to debug long running tests
   134  					// fmt.Println(a...)
   135  					res := fmt.Sprintln(a...)
   136  					return stdout.Write([]byte(res))
   137  				})
   138  				pkg.DefineGoNativeValue("Printf", func(format string, a ...interface{}) (n int, err error) {
   139  					res := fmt.Sprintf(format, a...)
   140  					return stdout.Write([]byte(res))
   141  				})
   142  				pkg.DefineGoNativeValue("Print", func(a ...interface{}) (n int, err error) {
   143  					res := fmt.Sprint(a...)
   144  					return stdout.Write([]byte(res))
   145  				})
   146  				pkg.DefineGoNativeValue("Sprint", fmt.Sprint)
   147  				pkg.DefineGoNativeValue("Sprintf", fmt.Sprintf)
   148  				pkg.DefineGoNativeValue("Sprintln", fmt.Sprintln)
   149  				pkg.DefineGoNativeValue("Sscanf", fmt.Sscanf)
   150  				pkg.DefineGoNativeValue("Errorf", fmt.Errorf)
   151  				pkg.DefineGoNativeValue("Fprintln", fmt.Fprintln)
   152  				pkg.DefineGoNativeValue("Fprintf", fmt.Fprintf)
   153  				pkg.DefineGoNativeValue("Fprint", fmt.Fprint)
   154  				return pkg, pkg.NewPackage()
   155  			case "encoding/base64":
   156  				pkg := gno.NewPackageNode("base64", pkgPath, nil)
   157  				pkg.DefineGoNativeValue("RawStdEncoding", base64.RawStdEncoding)
   158  				pkg.DefineGoNativeValue("StdEncoding", base64.StdEncoding)
   159  				pkg.DefineGoNativeValue("NewDecoder", base64.NewDecoder)
   160  				return pkg, pkg.NewPackage()
   161  			case "encoding/binary":
   162  				pkg := gno.NewPackageNode("binary", pkgPath, nil)
   163  				pkg.DefineGoNativeValue("LittleEndian", binary.LittleEndian)
   164  				pkg.DefineGoNativeValue("BigEndian", binary.BigEndian)
   165  				pkg.DefineGoNativeValue("Write", binary.BigEndian) // warn: use reflection
   166  				return pkg, pkg.NewPackage()
   167  			case "encoding/json":
   168  				pkg := gno.NewPackageNode("json", pkgPath, nil)
   169  				pkg.DefineGoNativeValue("Unmarshal", json.Unmarshal)
   170  				pkg.DefineGoNativeValue("Marshal", json.Marshal)
   171  				return pkg, pkg.NewPackage()
   172  			case "encoding/xml":
   173  				pkg := gno.NewPackageNode("xml", pkgPath, nil)
   174  				pkg.DefineGoNativeValue("Unmarshal", xml.Unmarshal)
   175  				return pkg, pkg.NewPackage()
   176  			case "internal/os_test":
   177  				pkg := gno.NewPackageNode("os_test", pkgPath, nil)
   178  				pkg.DefineNative("Sleep",
   179  					gno.Flds( // params
   180  						"d", gno.AnyT(), // NOTE: should be time.Duration
   181  					),
   182  					gno.Flds( // results
   183  					),
   184  					func(m *gno.Machine) {
   185  						// For testing purposes here, nanoseconds are separately kept track.
   186  						arg0 := m.LastBlock().GetParams1().TV
   187  						d := arg0.GetInt64()
   188  						sec := d / int64(time.Second)
   189  						nano := d % int64(time.Second)
   190  						ctx := m.Context.(stdlibs.ExecContext)
   191  						ctx.Timestamp += sec
   192  						ctx.TimestampNano += nano
   193  						if ctx.TimestampNano >= int64(time.Second) {
   194  							ctx.Timestamp += 1
   195  							ctx.TimestampNano -= int64(time.Second)
   196  						}
   197  						m.Context = ctx
   198  					},
   199  				)
   200  				return pkg, pkg.NewPackage()
   201  			case "net":
   202  				pkg := gno.NewPackageNode("net", pkgPath, nil)
   203  				pkg.DefineGoNativeType(reflect.TypeOf(net.TCPAddr{}))
   204  				pkg.DefineGoNativeValue("IPv4", net.IPv4)
   205  				return pkg, pkg.NewPackage()
   206  			case "net/url":
   207  				pkg := gno.NewPackageNode("url", pkgPath, nil)
   208  				pkg.DefineGoNativeType(reflect.TypeOf(url.Values{}))
   209  				return pkg, pkg.NewPackage()
   210  			case "bufio":
   211  				pkg := gno.NewPackageNode("bufio", pkgPath, nil)
   212  				pkg.DefineGoNativeValue("NewScanner", bufio.NewScanner)
   213  				pkg.DefineGoNativeType(reflect.TypeOf(bufio.SplitFunc(nil)))
   214  				return pkg, pkg.NewPackage()
   215  			case "bytes":
   216  				pkg := gno.NewPackageNode("bytes", pkgPath, nil)
   217  				pkg.DefineGoNativeValue("Equal", bytes.Equal)
   218  				pkg.DefineGoNativeValue("Compare", bytes.Compare)
   219  				pkg.DefineGoNativeValue("NewReader", bytes.NewReader)
   220  				pkg.DefineGoNativeValue("NewBuffer", bytes.NewBuffer)
   221  				pkg.DefineGoNativeValue("Repeat", bytes.Repeat)
   222  				pkg.DefineGoNativeType(reflect.TypeOf(bytes.Buffer{}))
   223  				return pkg, pkg.NewPackage()
   224  			case "time":
   225  				pkg := gno.NewPackageNode("time", pkgPath, nil)
   226  				pkg.DefineGoNativeValue("Millisecond", time.Millisecond)
   227  				pkg.DefineGoNativeValue("Second", time.Second)
   228  				pkg.DefineGoNativeValue("Minute", time.Minute)
   229  				pkg.DefineGoNativeValue("Hour", time.Hour)
   230  				pkg.DefineGoNativeValue("Date", time.Date)
   231  				pkg.DefineGoNativeValue("Now", func() time.Time { return time.Unix(0, 0).UTC() }) // deterministic
   232  				pkg.DefineGoNativeValue("November", time.November)
   233  				pkg.DefineGoNativeValue("UTC", time.UTC)
   234  				pkg.DefineGoNativeValue("Unix", time.Unix)
   235  				pkg.DefineGoNativeType(reflect.TypeOf(time.Time{}))
   236  				pkg.DefineGoNativeType(reflect.TypeOf(time.Duration(0)))
   237  				pkg.DefineGoNativeType(reflect.TypeOf(time.Month(0)))
   238  				return pkg, pkg.NewPackage()
   239  			case "strings":
   240  				pkg := gno.NewPackageNode("strings", pkgPath, nil)
   241  				pkg.DefineGoNativeValue("Split", strings.Split)
   242  				pkg.DefineGoNativeValue("SplitN", strings.SplitN)
   243  				pkg.DefineGoNativeValue("Contains", strings.Contains)
   244  				pkg.DefineGoNativeValue("TrimSpace", strings.TrimSpace)
   245  				pkg.DefineGoNativeValue("HasPrefix", strings.HasPrefix)
   246  				pkg.DefineGoNativeValue("NewReader", strings.NewReader)
   247  				pkg.DefineGoNativeValue("Index", strings.Index)
   248  				pkg.DefineGoNativeValue("IndexRune", strings.IndexRune)
   249  				pkg.DefineGoNativeValue("Join", strings.Join)
   250  				pkg.DefineGoNativeType(reflect.TypeOf(strings.Builder{}))
   251  				return pkg, pkg.NewPackage()
   252  			case "math":
   253  				pkg := gno.NewPackageNode("math", pkgPath, nil)
   254  				pkg.DefineGoNativeValue("Abs", math.Abs)
   255  				pkg.DefineGoNativeValue("Cos", math.Cos)
   256  				pkg.DefineGoNativeValue("Pi", math.Pi)
   257  				pkg.DefineGoNativeValue("Float64bits", math.Float64bits)
   258  				pkg.DefineGoNativeValue("Pi", math.Pi)
   259  				pkg.DefineGoNativeValue("MaxFloat32", math.MaxFloat32)
   260  				pkg.DefineGoNativeValue("MaxFloat64", math.MaxFloat64)
   261  				pkg.DefineGoNativeValue("MaxUint32", math.MaxUint32)
   262  				pkg.DefineGoNativeValue("MaxUint64", uint64(math.MaxUint64))
   263  				pkg.DefineGoNativeValue("MinInt8", math.MinInt8)
   264  				pkg.DefineGoNativeValue("MinInt16", math.MinInt16)
   265  				pkg.DefineGoNativeValue("MinInt32", math.MinInt32)
   266  				pkg.DefineGoNativeValue("MinInt64", math.MinInt64)
   267  				pkg.DefineGoNativeValue("MaxInt8", math.MaxInt8)
   268  				pkg.DefineGoNativeValue("MaxInt16", math.MaxInt16)
   269  				pkg.DefineGoNativeValue("MaxInt32", math.MaxInt32)
   270  				pkg.DefineGoNativeValue("MaxInt64", math.MaxInt64)
   271  				return pkg, pkg.NewPackage()
   272  			case "math/rand":
   273  				// XXX only expose for tests.
   274  				pkg := gno.NewPackageNode("rand", pkgPath, nil)
   275  				pkg.DefineGoNativeValue("Intn", rand.Intn)
   276  				pkg.DefineGoNativeValue("Uint32", rand.Uint32)
   277  				pkg.DefineGoNativeValue("Seed", rand.Seed)
   278  				pkg.DefineGoNativeValue("New", rand.New)
   279  				pkg.DefineGoNativeValue("NewSource", rand.NewSource)
   280  				pkg.DefineGoNativeType(reflect.TypeOf(rand.Rand{}))
   281  				return pkg, pkg.NewPackage()
   282  			case "crypto/rand":
   283  				pkg := gno.NewPackageNode("rand", pkgPath, nil)
   284  				pkg.DefineGoNativeValue("Prime", crand.Prime)
   285  				// for determinism:
   286  				// pkg.DefineGoNativeValue("Reader", crand.Reader)
   287  				pkg.DefineGoNativeValue("Reader", &dummyReader{})
   288  				return pkg, pkg.NewPackage()
   289  			case "crypto/md5":
   290  				pkg := gno.NewPackageNode("md5", pkgPath, nil)
   291  				pkg.DefineGoNativeValue("New", md5.New)
   292  				return pkg, pkg.NewPackage()
   293  			case "crypto/sha1":
   294  				pkg := gno.NewPackageNode("sha1", pkgPath, nil)
   295  				pkg.DefineGoNativeValue("New", sha1.New)
   296  				return pkg, pkg.NewPackage()
   297  			case "image":
   298  				pkg := gno.NewPackageNode("image", pkgPath, nil)
   299  				pkg.DefineGoNativeType(reflect.TypeOf(image.Point{}))
   300  				return pkg, pkg.NewPackage()
   301  			case "image/color":
   302  				pkg := gno.NewPackageNode("color", pkgPath, nil)
   303  				pkg.DefineGoNativeType(reflect.TypeOf(color.NRGBA64{}))
   304  				return pkg, pkg.NewPackage()
   305  			case "compress/flate":
   306  				pkg := gno.NewPackageNode("flate", pkgPath, nil)
   307  				pkg.DefineGoNativeValue("BestSpeed", flate.BestSpeed)
   308  				return pkg, pkg.NewPackage()
   309  			case "compress/gzip":
   310  				pkg := gno.NewPackageNode("gzip", pkgPath, nil)
   311  				pkg.DefineGoNativeType(reflect.TypeOf(gzip.Writer{}))
   312  				pkg.DefineGoNativeValue("BestCompression", gzip.BestCompression)
   313  				pkg.DefineGoNativeValue("BestSpeed", gzip.BestSpeed)
   314  				return pkg, pkg.NewPackage()
   315  			case "context":
   316  				pkg := gno.NewPackageNode("context", pkgPath, nil)
   317  				pkg.DefineGoNativeType(reflect.TypeOf((*context.Context)(nil)).Elem())
   318  				pkg.DefineGoNativeValue("WithValue", context.WithValue)
   319  				pkg.DefineGoNativeValue("Background", context.Background)
   320  				return pkg, pkg.NewPackage()
   321  			case "sync":
   322  				pkg := gno.NewPackageNode("sync", pkgPath, nil)
   323  				pkg.DefineGoNativeType(reflect.TypeOf(sync.Mutex{}))
   324  				pkg.DefineGoNativeType(reflect.TypeOf(sync.RWMutex{}))
   325  				pkg.DefineGoNativeType(reflect.TypeOf(sync.Pool{}))
   326  				return pkg, pkg.NewPackage()
   327  			case "sync/atomic":
   328  				pkg := gno.NewPackageNode("atomic", pkgPath, nil)
   329  				pkg.DefineGoNativeType(reflect.TypeOf(atomic.Value{}))
   330  				return pkg, pkg.NewPackage()
   331  			case "math/big":
   332  				pkg := gno.NewPackageNode("big", pkgPath, nil)
   333  				pkg.DefineGoNativeValue("NewInt", big.NewInt)
   334  				return pkg, pkg.NewPackage()
   335  			case "sort":
   336  				pkg := gno.NewPackageNode("sort", pkgPath, nil)
   337  				pkg.DefineGoNativeValue("Strings", sort.Strings)
   338  				// pkg.DefineGoNativeValue("Sort", sort.Sort)
   339  				return pkg, pkg.NewPackage()
   340  			case "flag":
   341  				pkg := gno.NewPackageNode("flag", pkgPath, nil)
   342  				pkg.DefineGoNativeType(reflect.TypeOf(flag.Flag{}))
   343  				return pkg, pkg.NewPackage()
   344  			case "io":
   345  				pkg := gno.NewPackageNode("io", pkgPath, nil)
   346  				pkg.DefineGoNativeValue("EOF", io.EOF)
   347  				pkg.DefineGoNativeValue("NopCloser", io.NopCloser)
   348  				pkg.DefineGoNativeValue("ReadFull", io.ReadFull)
   349  				pkg.DefineGoNativeValue("ReadAll", io.ReadAll)
   350  				pkg.DefineGoNativeType(reflect.TypeOf((*io.ReadCloser)(nil)).Elem())
   351  				pkg.DefineGoNativeType(reflect.TypeOf((*io.Closer)(nil)).Elem())
   352  				pkg.DefineGoNativeType(reflect.TypeOf((*io.Reader)(nil)).Elem())
   353  				return pkg, pkg.NewPackage()
   354  			case "log":
   355  				pkg := gno.NewPackageNode("log", pkgPath, nil)
   356  				pkg.DefineGoNativeValue("Fatal", log.Fatal)
   357  				return pkg, pkg.NewPackage()
   358  			case "text/template":
   359  				pkg := gno.NewPackageNode("template", pkgPath, nil)
   360  				pkg.DefineGoNativeType(reflect.TypeOf(template.FuncMap{}))
   361  				return pkg, pkg.NewPackage()
   362  			case "unicode/utf8":
   363  				pkg := gno.NewPackageNode("utf8", pkgPath, nil)
   364  				pkg.DefineGoNativeValue("DecodeRuneInString", utf8.DecodeRuneInString)
   365  				tv := gno.TypedValue{T: gno.UntypedRuneType} // TODO dry
   366  				tv.SetInt32(utf8.RuneSelf)                   // ..
   367  				pkg.Define("RuneSelf", tv)                   // ..
   368  				return pkg, pkg.NewPackage()
   369  			case "errors":
   370  				pkg := gno.NewPackageNode("errors", pkgPath, nil)
   371  				pkg.DefineGoNativeValue("New", errors.New)
   372  				return pkg, pkg.NewPackage()
   373  			case "hash/fnv":
   374  				pkg := gno.NewPackageNode("fnv", pkgPath, nil)
   375  				pkg.DefineGoNativeValue("New32a", fnv.New32a)
   376  				return pkg, pkg.NewPackage()
   377  			default:
   378  				// continue on...
   379  			}
   380  		}
   381  
   382  		// if native package is preferred, try to load stdlibs/* as backup.
   383  		if mode == ImportModeNativePreferred {
   384  			pn, pv = loadStdlib(rootDir, pkgPath, newStore, stdout)
   385  			if pn != nil {
   386  				return
   387  			}
   388  		}
   389  
   390  		// if examples package...
   391  		examplePath := filepath.Join(rootDir, "examples", pkgPath)
   392  		if osm.DirExists(examplePath) {
   393  			memPkg := gno.ReadMemPackage(examplePath, pkgPath)
   394  			if memPkg.IsEmpty() {
   395  				panic(fmt.Sprintf("found an empty package %q", pkgPath))
   396  			}
   397  
   398  			send := std.Coins{}
   399  			ctx := testContext(pkgPath, send)
   400  			m2 := gno.NewMachineWithOptions(gno.MachineOptions{
   401  				PkgPath: "test",
   402  				Output:  stdout,
   403  				Store:   newStore,
   404  				Context: ctx,
   405  			})
   406  			pn, pv = m2.RunMemPackage(memPkg, true)
   407  			return
   408  		}
   409  		return nil, nil
   410  	}
   411  	// NOTE: store is also used in closure above.
   412  	db := memdb.NewMemDB()
   413  	baseStore := dbadapter.StoreConstructor(db, stypes.StoreOptions{})
   414  	iavlStore := iavl.StoreConstructor(db, stypes.StoreOptions{})
   415  	store = gno.NewStore(nil, baseStore, iavlStore)
   416  	store.SetPackageGetter(getPackage)
   417  	store.SetNativeStore(teststdlibs.NativeStore)
   418  	store.SetPackageInjector(testPackageInjector)
   419  	store.SetStrictGo2GnoMapping(false)
   420  	return
   421  }
   422  
   423  func loadStdlib(rootDir, pkgPath string, store gno.Store, stdout io.Writer) (*gno.PackageNode, *gno.PackageValue) {
   424  	dirs := [...]string{
   425  		// normal stdlib path.
   426  		filepath.Join(rootDir, "gnovm", "stdlibs", pkgPath),
   427  		// override path. definitions here override the previous if duplicate.
   428  		filepath.Join(rootDir, "gnovm", "tests", "stdlibs", pkgPath),
   429  	}
   430  	files := make([]string, 0, 32) // pre-alloc 32 as a likely high number of files
   431  	for _, path := range dirs {
   432  		dl, err := os.ReadDir(path)
   433  		if err != nil {
   434  			if os.IsNotExist(err) {
   435  				continue
   436  			}
   437  			panic(fmt.Errorf("could not access dir %q: %w", path, err))
   438  		}
   439  
   440  		for _, f := range dl {
   441  			// NOTE: RunMemPackage has other rules; those should be mostly useful
   442  			// for on-chain packages (ie. include README and gno.mod).
   443  			if !f.IsDir() && strings.HasSuffix(f.Name(), ".gno") {
   444  				files = append(files, filepath.Join(path, f.Name()))
   445  			}
   446  		}
   447  	}
   448  	if len(files) == 0 {
   449  		return nil, nil
   450  	}
   451  
   452  	memPkg := gno.ReadMemPackageFromList(files, pkgPath)
   453  	m2 := gno.NewMachineWithOptions(gno.MachineOptions{
   454  		// NOTE: see also pkgs/sdk/vm/builtins.go
   455  		// Needs PkgPath != its name because TestStore.getPackage is the package
   456  		// getter for the store, which calls loadStdlib, so it would be recursively called.
   457  		PkgPath: "stdlibload",
   458  		Output:  stdout,
   459  		Store:   store,
   460  	})
   461  	save := pkgPath != "testing" // never save the "testing" package
   462  	return m2.RunMemPackageWithOverrides(memPkg, save)
   463  }
   464  
   465  func testPackageInjector(store gno.Store, pn *gno.PackageNode) {
   466  	// Test specific injections:
   467  	switch pn.PkgPath {
   468  	case "strconv":
   469  		// NOTE: Itoa and Atoi are already injected
   470  		// from stdlibs.InjectNatives.
   471  		pn.DefineGoNativeType(reflect.TypeOf(strconv.NumError{}))
   472  		pn.DefineGoNativeValue("ParseInt", strconv.ParseInt)
   473  	}
   474  }
   475  
   476  //----------------------------------------
   477  
   478  type dummyReader struct{}
   479  
   480  func (*dummyReader) Read(b []byte) (n int, err error) {
   481  	for i := 0; i < len(b); i++ {
   482  		b[i] = byte((100 + i) % 256)
   483  	}
   484  	return len(b), nil
   485  }
   486  
   487  //----------------------------------------
   488  
   489  type TestReport struct {
   490  	Name    string
   491  	Verbose bool
   492  	Failed  bool
   493  	Skipped bool
   494  	Output  string
   495  }