github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/gnovm/pkg/repl/repl_test.go (about)

     1  package repl
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/require"
     7  )
     8  
     9  type step struct {
    10  	Line   string
    11  	Error  string
    12  	Result string
    13  }
    14  
    15  var fixtures = []struct {
    16  	Name      string
    17  	CodeSteps []step
    18  }{
    19  	{
    20  		Name: "Add new import",
    21  		CodeSteps: []step{
    22  			{
    23  				Line:   "import \"fmt\"\nimport \"os\"",
    24  				Result: "import \"fmt\"\nimport \"os\"\n",
    25  			},
    26  		},
    27  	},
    28  	{
    29  		Name: "Add new constant",
    30  		CodeSteps: []step{
    31  			{
    32  				Line:   "const test2, test3 = \"test_string2\", \"test_string3\"",
    33  				Result: "const test2, test3 = \"test_string2\", \"test_string3\"\n",
    34  			},
    35  			{
    36  				Line:   "const test = \"test_string\"",
    37  				Result: "const test = \"test_string\"\n",
    38  			},
    39  		},
    40  	},
    41  	{
    42  		Name: "Add struct and functions",
    43  		CodeSteps: []step{
    44  			{
    45  				Line:   "type MyStruct struct { count int}",
    46  				Result: "type MyStruct struct{ count int }\n",
    47  			},
    48  			{
    49  				Line:   "func (s *MyStruct) Add(){s.count++}",
    50  				Result: "func (s *MyStruct) Add()\t{ s.count++ }\n",
    51  			},
    52  		},
    53  	},
    54  	{
    55  		Name: "Add new var",
    56  		CodeSteps: []step{
    57  			{
    58  				Line:   "var test2, test3 string = \"test_string2\", \"test_string3\"",
    59  				Result: "var test2, test3 string = \"test_string2\", \"test_string3\"\n",
    60  			},
    61  			{
    62  				Line:   "var test int = 42",
    63  				Result: "var test int = 42\n",
    64  			},
    65  		},
    66  	},
    67  	{
    68  		Name: "Add wrong code",
    69  		CodeSteps: []step{
    70  			{
    71  				Line:  "importasdasd",
    72  				Error: "test/test1.gno:7: name importasdasd not declared",
    73  			},
    74  			{
    75  				Line: "var a := 1",
    76  				// we cannot check the entire error because it is different depending on the used Go version.
    77  				Error: "error parsing code:",
    78  			},
    79  		},
    80  	},
    81  	{
    82  		Name: "Add function and use it",
    83  		CodeSteps: []step{
    84  			{
    85  				Line:   "func sum(a,b int)int{return a+b}",
    86  				Result: "func sum(a, b int) int\t{ return a + b }\n",
    87  			},
    88  			{
    89  				Line:   "import \"fmt\"",
    90  				Result: "import \"fmt\"\n",
    91  			},
    92  			{
    93  				Line:   "fmt.Println(sum(1,1))",
    94  				Result: "2\n",
    95  			},
    96  		},
    97  	},
    98  	{
    99  		Name: "All declarations at once",
   100  		CodeSteps: []step{
   101  			{
   102  				Line:   "import \"fmt\"\nfunc sum(a,b int)int{return a+b}",
   103  				Result: "import \"fmt\"\nfunc sum(a, b int) int\t{ return a + b }\n",
   104  			},
   105  			{
   106  				Line:   "fmt.Println(sum(1,1))",
   107  				Result: "2\n",
   108  			},
   109  		},
   110  	},
   111  	{
   112  		Name: "Fibonacci",
   113  		CodeSteps: []step{
   114  			{
   115  				Line: `
   116  				func fib(n int)int {
   117  					if n < 2 {
   118  						return n
   119  					}
   120  					return fib(n-2) + fib(n-1)
   121  				}
   122  				`,
   123  				Result: "func fib(n int) int {\n\tif n < 2 {\n\t\treturn n\n\t}\n\treturn fib(n-2) + fib(n-1)\n}\n",
   124  			},
   125  			{
   126  				Line:   "println(fib(24))",
   127  				Result: "46368\n",
   128  			},
   129  		},
   130  	},
   131  	{
   132  		Name: "Meaning of life",
   133  		CodeSteps: []step{
   134  			{
   135  				Line: `
   136  				const (
   137  					oneConst   = 1
   138  					tenConst   = 10
   139  					magicConst = 19
   140  				)
   141  				`,
   142  				Result: "const (\n\toneConst\t= 1\n\ttenConst\t= 10\n\tmagicConst\t= 19\n)\n",
   143  			},
   144  			{
   145  				Line:   "var outVar int",
   146  				Result: "var outVar int\n",
   147  			},
   148  			{
   149  				Line: `
   150  				type MyStruct struct {
   151  					counter int
   152  				}
   153  				
   154  				func (s *MyStruct) Add() {
   155  					s.counter++
   156  				}
   157  				
   158  				func (s *MyStruct) Get() int {
   159  					return s.counter
   160  				}
   161  				`,
   162  				Result: "type MyStruct struct {\n\tcounter int\n}\nfunc (s *MyStruct) Add() {\n\ts.counter++\n}\nfunc (s *MyStruct) Get() int {\n\treturn s.counter\n}\n",
   163  			},
   164  			{
   165  				Line: `
   166  				ms := &MyStruct{counter: 10}
   167  
   168  				ms.Add()
   169  				ms.Add()
   170  
   171  				outVar = ms.Get() + oneConst + tenConst + magicConst
   172  
   173  				println(outVar)
   174  				`,
   175  				Result: "42\n",
   176  			},
   177  		},
   178  	},
   179  }
   180  
   181  func TestRepl(t *testing.T) {
   182  	for _, fix := range fixtures {
   183  		fix := fix
   184  		t.Run(fix.Name, func(t *testing.T) {
   185  			r := NewRepl()
   186  			for _, cs := range fix.CodeSteps {
   187  				out, err := r.Process(cs.Line)
   188  				if cs.Error == "" {
   189  					require.NoError(t, err)
   190  				} else {
   191  					require.Error(t, err)
   192  					require.Contains(t, err.Error(), cs.Error)
   193  				}
   194  
   195  				require.Equal(t, cs.Result, out)
   196  			}
   197  		})
   198  	}
   199  }
   200  
   201  func TestReplOpts(t *testing.T) {
   202  	t.Parallel()
   203  
   204  	require := require.New(t)
   205  
   206  	r := NewRepl(WithStd(nil, nil, nil), WithStore(nil))
   207  	require.Nil(r.storeFunc())
   208  	require.Nil(r.stderr)
   209  	require.Nil(r.stdin)
   210  	require.Nil(r.stdout)
   211  
   212  	_, err := r.Process("import \"fmt\"")
   213  	require.NoError(err)
   214  }
   215  
   216  func TestReplReset(t *testing.T) {
   217  	t.Parallel()
   218  
   219  	require := require.New(t)
   220  
   221  	r := NewRepl()
   222  
   223  	_, err := r.Process("println(\"hi\")")
   224  	require.NoError(err)
   225  	o := r.Src()
   226  	require.Contains(o, "generated by 'gno repl'")
   227  	r.Reset()
   228  	o = r.Src()
   229  	require.NotContains(o, "generated by 'gno repl'")
   230  }