diff --git a/gnovm/pkg/gnolang/machine_test.go b/gnovm/pkg/gnolang/machine_test.go index c2ab8ea12c5..555b6ec8307 100644 --- a/gnovm/pkg/gnolang/machine_test.go +++ b/gnovm/pkg/gnolang/machine_test.go @@ -9,7 +9,6 @@ import ( "github.com/gnolang/gno/tm2/pkg/store/dbadapter" "github.com/gnolang/gno/tm2/pkg/store/iavl" stypes "github.com/gnolang/gno/tm2/pkg/store/types" - "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/assert" ) @@ -109,9 +108,7 @@ func TestMachineString(t *testing.T) { for _, tt := range cases { t.Run(tt.name, func(t *testing.T) { got := tt.in.String() - if diff := cmp.Diff(got, tt.want); diff != "" { - t.Fatalf("Mismatch: got - want +\n%s", diff) - } + assert.Equal(t, tt.want, got) }) } } diff --git a/gnovm/pkg/gnolang/uverse.go b/gnovm/pkg/gnolang/uverse.go index bea11272049..ce6260fffcf 100644 --- a/gnovm/pkg/gnolang/uverse.go +++ b/gnovm/pkg/gnolang/uverse.go @@ -1,8 +1,9 @@ package gnolang import ( + "bytes" "fmt" - "strings" + "io" bm "github.com/gnolang/gno/gnovm/pkg/benchops" ) @@ -708,6 +709,7 @@ func makeUverseNode() { return }, ) + // NOTE: panic is its own statement type, and is not defined as a function. defNative("print", Flds( // params @@ -716,18 +718,7 @@ func makeUverseNode() { nil, // results func(m *Machine) { arg0 := m.LastBlock().GetParams1() - xv := arg0 - xvl := xv.TV.GetLength() - ss := make([]string, xvl) - for i := 0; i < xvl; i++ { - ev := xv.TV.GetPointerAtIndexInt(m.Store, i).Deref() - ss[i] = ev.Sprint(m) - } - rs := strings.Join(ss, " ") - if debug { - print(rs) - } - m.Output.Write([]byte(rs)) + uversePrint(m, arg0, false) }, ) defNative("println", @@ -737,18 +728,7 @@ func makeUverseNode() { nil, // results func(m *Machine) { arg0 := m.LastBlock().GetParams1() - xv := arg0 - xvl := xv.TV.GetLength() - ss := make([]string, xvl) - for i := 0; i < xvl; i++ { - ev := xv.TV.GetPointerAtIndexInt(m.Store, i).Deref() - ss[i] = ev.Sprint(m) - } - rs := strings.Join(ss, " ") + "\n" - if debug { - println("DEBUG/stdout: " + rs) - } - m.Output.Write([]byte(rs)) + uversePrint(m, arg0, true) }, ) defNative("recover", @@ -786,3 +766,38 @@ func copyListToRunes(dst []rune, tvs []TypedValue) { dst[i] = tvs[i].GetInt32() } } + +// uversePrint is used for the print and println functions. +// println passes newline = true. +// xv contains the variadic argument passed to the function. +func uversePrint(m *Machine, xv PointerValue, newline bool) { + xvl := xv.TV.GetLength() + switch xvl { + case 0: + if newline { + m.Output.Write(bNewline) + } + case 1: + ev := xv.TV.GetPointerAtIndexInt(m.Store, 0).Deref() + res := ev.Sprint(m) + io.WriteString(m.Output, res) + if newline { + m.Output.Write(bNewline) + } + default: + var buf bytes.Buffer + for i := 0; i < xvl; i++ { + if i != 0 { // Not the last item. + buf.WriteByte(' ') + } + ev := xv.TV.GetPointerAtIndexInt(m.Store, i).Deref() + buf.WriteString(ev.Sprint(m)) + } + if newline { + buf.WriteByte('\n') + } + m.Output.Write(buf.Bytes()) + } +} + +var bNewline = []byte("\n") diff --git a/gnovm/pkg/gnolang/uverse_test.go b/gnovm/pkg/gnolang/uverse_test.go index 76961b70ccb..4c617784160 100644 --- a/gnovm/pkg/gnolang/uverse_test.go +++ b/gnovm/pkg/gnolang/uverse_test.go @@ -1,7 +1,15 @@ package gnolang import ( + "bytes" "testing" + + "github.com/gnolang/gno/gnovm" + "github.com/gnolang/gno/tm2/pkg/db/memdb" + "github.com/gnolang/gno/tm2/pkg/store/dbadapter" + "github.com/gnolang/gno/tm2/pkg/store/iavl" + stypes "github.com/gnolang/gno/tm2/pkg/store/types" + "github.com/stretchr/testify/assert" ) type uverseTestCases struct { @@ -158,3 +166,135 @@ func TestIssue1337PrintNilSliceAsUndefined(t *testing.T) { }) } } + +var pSink any = nil + +func BenchmarkGnoPrintln(b *testing.B) { + var buf bytes.Buffer + db := memdb.NewMemDB() + baseStore := dbadapter.StoreConstructor(db, stypes.StoreOptions{}) + iavlStore := iavl.StoreConstructor(db, stypes.StoreOptions{}) + store := NewStore(nil, baseStore, iavlStore) + + m := NewMachineWithOptions(MachineOptions{ + Output: &buf, + Store: store, + }) + + program := `package p + func main() { + for i := 0; i < 1000; i++ { + println("abcdeffffffffffffffff1222 11111 11111") + } + }` + m.RunMemPackage(&gnovm.MemPackage{ + Name: "p", + Path: "p", + Files: []*gnovm.MemFile{ + {Name: "a.gno", Body: program}, + }, + }, false) + + b.ReportAllocs() + b.ResetTimer() + + for i := 0; i < b.N; i++ { + buf.Reset() + m.RunStatement(S(Call(Nx("main")))) + pSink = buf.String() + } + + if pSink == nil { + b.Fatal("Benchmark did not run!") + } + pSink = nil +} + +func TestGnoPrintAndPrintln(t *testing.T) { + tests := []struct { + name string + srcArgs string + want string + }{ + { + "print with no args", + "print()", + "", + }, + { + "print with 1 arg", + `print("1")`, + "1", + }, + { + "print with 2 args", + `print("1", 2)`, + "1 2", + }, + { + "print with 3 args", + `print("1", 2, "*")`, + "1 2 *", + }, + { + "print with own spaces", + `print("1 ", 2, "*")`, + "1 2 *", + }, + { + "println with no args", + "println()", + "\n", + }, + { + "print with 1 arg", + `println("1")`, + "1\n", + }, + { + "println with 2 args", + `println("1", 2)`, + "1 2\n", + }, + { + "println with 3 args", + `println("1", 2, "*")`, + "1 2 *\n", + }, + { + "println with own spaces", + `println("1 ", 2, "*")`, + "1 2 *\n", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var buf bytes.Buffer + db := memdb.NewMemDB() + baseStore := dbadapter.StoreConstructor(db, stypes.StoreOptions{}) + iavlStore := iavl.StoreConstructor(db, stypes.StoreOptions{}) + store := NewStore(nil, baseStore, iavlStore) + + m := NewMachineWithOptions(MachineOptions{ + Output: &buf, + Store: store, + }) + + program := `package p + func main() {` + tt.srcArgs + "\n}" + m.RunMemPackage(&gnovm.MemPackage{ + Name: "p", + Path: "p", + Files: []*gnovm.MemFile{ + {Name: "a.gno", Body: program}, + }, + }, false) + + buf.Reset() + m.RunStatement(S(Call(Nx("main")))) + got := buf.String() + assert.Equal(t, tt.want, got) + }) + } +} diff --git a/go.mod b/go.mod index 026351cec77..978e2e69d36 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,6 @@ require ( github.com/davecgh/go-spew v1.1.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 github.com/fortytw2/leaktest v1.3.0 - github.com/google/go-cmp v0.6.0 github.com/google/gofuzz v1.2.0 github.com/gorilla/websocket v1.5.3 github.com/libp2p/go-buffer-pool v0.1.0 diff --git a/tm2/pkg/bft/rpc/lib/server/write_endpoints_test.go b/tm2/pkg/bft/rpc/lib/server/write_endpoints_test.go index b01144f9273..3402012b458 100644 --- a/tm2/pkg/bft/rpc/lib/server/write_endpoints_test.go +++ b/tm2/pkg/bft/rpc/lib/server/write_endpoints_test.go @@ -6,7 +6,6 @@ import ( "net/http/httptest" "testing" - "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/assert" types "github.com/gnolang/gno/tm2/pkg/bft/rpc/lib/types" @@ -27,7 +26,5 @@ func TestWriteListOfEndpoints(t *testing.T) { assert.NoError(t, err) gotResp := string(blob) wantResp := `
Available endpoints:
//localhost/d

Endpoints that require arguments:
//localhost/c?s=_&i=_
` - if diff := cmp.Diff(gotResp, wantResp); diff != "" { - t.Fatalf("Mismatch response: got - want +\n%s", diff) - } + assert.Equal(t, wantResp, gotResp) } diff --git a/tm2/pkg/sdk/auth/params_test.go b/tm2/pkg/sdk/auth/params_test.go index 36a52ac9001..1cdecf35c2a 100644 --- a/tm2/pkg/sdk/auth/params_test.go +++ b/tm2/pkg/sdk/auth/params_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -123,9 +123,7 @@ func TestParamsString(t *testing.T) { for _, tt := range cases { t.Run(tt.name, func(t *testing.T) { got := tt.params.String() - if diff := cmp.Diff(got, tt.want); diff != "" { - t.Fatalf("Mismatch: got - want +\n%s", diff) - } + assert.Equal(t, tt.want, got) }) } }