github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/gnovm/pkg/transpiler/transpiler_test.go (about) 1 package transpiler 2 3 import ( 4 "go/ast" 5 goscanner "go/scanner" 6 "go/token" 7 "strings" 8 "testing" 9 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 ) 13 14 func TestTranspile(t *testing.T) { 15 t.Parallel() 16 17 cases := []struct { 18 name string 19 tags string 20 source string 21 expectedOutput string 22 expectedImports []*ast.ImportSpec 23 expectedError string 24 }{ 25 { 26 name: "hello", 27 source: ` 28 package foo 29 30 func hello() string { return "world"} 31 `, 32 expectedOutput: ` 33 // Code generated by github.com/gnolang/gno. DO NOT EDIT. 34 35 //line foo.gno:1:1 36 package foo 37 38 func hello() string { return "world" } 39 `, 40 }, 41 { 42 name: "hello with tags", 43 tags: "gno", 44 source: ` 45 package foo 46 47 func hello() string { return "world"} 48 `, 49 expectedOutput: ` 50 // Code generated by github.com/gnolang/gno. DO NOT EDIT. 51 52 //go:build gno 53 54 //line foo.gno:1:1 55 package foo 56 57 func hello() string { return "world" } 58 `, 59 }, 60 { 61 name: "use-std", 62 source: ` 63 package foo 64 65 import "std" 66 67 func hello() string { 68 _ = std.Foo 69 return "world" 70 } 71 `, 72 expectedOutput: ` 73 // Code generated by github.com/gnolang/gno. DO NOT EDIT. 74 75 //line foo.gno:1:1 76 package foo 77 78 import "github.com/gnolang/gno/gnovm/stdlibs/stdshim" 79 80 func hello() string { 81 _ = std.Foo 82 return "world" 83 } 84 `, 85 expectedImports: []*ast.ImportSpec{ 86 { 87 Path: &ast.BasicLit{ 88 ValuePos: 21, 89 Kind: 9, 90 Value: `"github.com/gnolang/gno/gnovm/stdlibs/stdshim"`, 91 }, 92 EndPos: 26, 93 }, 94 }, 95 }, 96 { 97 name: "use-realm", 98 source: ` 99 package foo 100 101 import "gno.land/r/users" 102 103 func foo() { _ = users.Register} 104 `, 105 expectedOutput: ` 106 // Code generated by github.com/gnolang/gno. DO NOT EDIT. 107 108 //line foo.gno:1:1 109 package foo 110 111 import "github.com/gnolang/gno/examples/gno.land/r/users" 112 113 func foo() { _ = users.Register } 114 `, 115 expectedImports: []*ast.ImportSpec{ 116 { 117 Path: &ast.BasicLit{ 118 ValuePos: 21, 119 Kind: 9, 120 Value: `"github.com/gnolang/gno/examples/gno.land/r/users"`, 121 }, 122 EndPos: 39, 123 }, 124 }, 125 }, 126 { 127 name: "use-avl", 128 source: ` 129 package foo 130 131 import "gno.land/p/demo/avl" 132 133 func foo() { _ = avl.Tree } 134 `, 135 expectedOutput: ` 136 // Code generated by github.com/gnolang/gno. DO NOT EDIT. 137 138 //line foo.gno:1:1 139 package foo 140 141 import "github.com/gnolang/gno/examples/gno.land/p/demo/avl" 142 143 func foo() { _ = avl.Tree } 144 `, 145 expectedImports: []*ast.ImportSpec{ 146 { 147 Path: &ast.BasicLit{ 148 ValuePos: 21, 149 Kind: 9, 150 Value: `"github.com/gnolang/gno/examples/gno.land/p/demo/avl"`, 151 }, 152 EndPos: 42, 153 }, 154 }, 155 }, 156 { 157 name: "use-named-std", 158 source: ` 159 package foo 160 161 import bar "std" 162 163 func hello() string { 164 _ = bar.Foo 165 return "world" 166 } 167 `, 168 expectedOutput: ` 169 // Code generated by github.com/gnolang/gno. DO NOT EDIT. 170 171 //line foo.gno:1:1 172 package foo 173 174 import bar "github.com/gnolang/gno/gnovm/stdlibs/stdshim" 175 176 func hello() string { 177 _ = bar.Foo 178 return "world" 179 } 180 `, 181 expectedImports: []*ast.ImportSpec{ 182 { 183 Name: &ast.Ident{ 184 NamePos: 21, 185 Name: "bar", 186 }, 187 Path: &ast.BasicLit{ 188 ValuePos: 25, 189 Kind: 9, 190 Value: `"github.com/gnolang/gno/gnovm/stdlibs/stdshim"`, 191 }, 192 EndPos: 30, 193 }, 194 }, 195 }, 196 { 197 name: "blacklisted-package", 198 source: ` 199 package foo 200 201 import "reflect" 202 203 func foo() { _ = reflect.ValueOf } 204 `, 205 expectedError: `transpileAST: foo.gno:3:8: import "reflect" is not in the whitelist`, 206 }, 207 { 208 name: "syntax-error", 209 source: ` 210 package foo 211 212 invalid 213 `, 214 expectedError: `parse: foo.gno:3:1: expected declaration, found invalid`, 215 }, 216 { 217 name: "unknown-realm", 218 source: ` 219 package foo 220 221 import "gno.land/p/demo/unknownxyz" 222 `, 223 expectedOutput: ` 224 // Code generated by github.com/gnolang/gno. DO NOT EDIT. 225 226 //line foo.gno:1:1 227 package foo 228 229 import "github.com/gnolang/gno/examples/gno.land/p/demo/unknownxyz" 230 `, 231 expectedImports: []*ast.ImportSpec{ 232 { 233 Path: &ast.BasicLit{ 234 ValuePos: 21, 235 Kind: 9, 236 Value: `"github.com/gnolang/gno/examples/gno.land/p/demo/unknownxyz"`, 237 }, 238 EndPos: 49, 239 }, 240 }, 241 }, 242 { 243 name: "whitelisted-package", 244 source: ` 245 package foo 246 247 import "regexp" 248 249 func foo() { _ = regexp.MatchString } 250 `, 251 expectedOutput: ` 252 // Code generated by github.com/gnolang/gno. DO NOT EDIT. 253 254 //line foo.gno:1:1 255 package foo 256 257 import "regexp" 258 259 func foo() { _ = regexp.MatchString } 260 `, 261 expectedImports: []*ast.ImportSpec{ 262 { 263 Path: &ast.BasicLit{ 264 ValuePos: 21, 265 Kind: 9, 266 Value: `"regexp"`, 267 }, 268 }, 269 }, 270 }, 271 } 272 for _, c := range cases { 273 c := c // scopelint 274 t.Run(c.name, func(t *testing.T) { 275 t.Parallel() 276 // "\n" is added for better test case readability, now trim it 277 source := strings.TrimPrefix(c.source, "\n") 278 279 res, err := Transpile(source, c.tags, "foo.gno") 280 281 if c.expectedError != "" { 282 require.EqualError(t, err, c.expectedError) 283 return 284 } 285 require.NoError(t, err) 286 expectedOutput := strings.TrimPrefix(c.expectedOutput, "\n") 287 assert.Equal(t, expectedOutput, res.Translated, "wrong output") 288 assert.Equal(t, c.expectedImports, res.Imports, "wrong imports") 289 }) 290 } 291 } 292 293 func TestParseGoBuildErrors(t *testing.T) { 294 tests := []struct { 295 name string 296 output string 297 expectedError error 298 }{ 299 { 300 name: "empty output", 301 output: "", 302 expectedError: nil, 303 }, 304 { 305 name: "random output", 306 output: "xxx", 307 expectedError: nil, 308 }, 309 { 310 name: "some errors", 311 output: `xxx 312 main.gno:6:2: nasty error 313 pkg/file.gno:60:20: ugly error`, 314 expectedError: goscanner.ErrorList{ 315 &goscanner.Error{ 316 Pos: token.Position{ 317 Filename: "main.gno", 318 Line: 6, 319 Column: 2, 320 }, 321 Msg: "nasty error", 322 }, 323 &goscanner.Error{ 324 Pos: token.Position{ 325 Filename: "pkg/file.gno", 326 Line: 60, 327 Column: 20, 328 }, 329 Msg: "ugly error", 330 }, 331 }, 332 }, 333 } 334 for _, tt := range tests { 335 t.Run(tt.name, func(t *testing.T) { 336 err := parseGoBuildErrors(tt.output) 337 338 assert.Equal(t, tt.expectedError, err) 339 }) 340 } 341 }