github.com/goplus/gop@v1.2.6/x/build/build_test.go (about) 1 /* 2 * Copyright (c) 2022 The GoPlus Authors (goplus.org). All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package build_test 18 19 import ( 20 "bytes" 21 "fmt" 22 "go/printer" 23 "go/types" 24 "os" 25 "path" 26 "path/filepath" 27 "strings" 28 "testing" 29 30 "github.com/goplus/gop/cl" 31 "github.com/goplus/gop/parser/fsx" 32 "github.com/goplus/gop/x/build" 33 ) 34 35 var ( 36 ctx = build.Default() 37 ) 38 39 func init() { 40 cl.SetDebug(cl.FlagNoMarkAutogen) 41 ctx.LoadConfig = func(cfg *cl.Config) { 42 cfg.NoFileLine = true 43 } 44 build.RegisterClassFileType(".tspx", "MyGame", []*build.Class{ 45 {Ext: ".tspx", Class: "Sprite"}, 46 }, "github.com/goplus/gop/cl/internal/spx") 47 build.RegisterClassFileType("_yap.gox", "App", nil, "github.com/goplus/yap") 48 } 49 50 func gopClTest(t *testing.T, gopcode interface{}, expected string) { 51 gopClTestEx(t, "main.gop", gopcode, expected) 52 } 53 54 func gopClTestEx(t *testing.T, filename string, gopcode interface{}, expected string) { 55 data, err := ctx.BuildFile(filename, gopcode) 56 if err != nil { 57 t.Fatalf("build gop error: %v", err) 58 } 59 if string(data) != expected { 60 fmt.Println("build gop error:") 61 fmt.Println(string(data)) 62 t.Fail() 63 } 64 } 65 66 func testKind(t *testing.T, name string, proj, class bool) { 67 isProj, ok := build.ClassKind(name) 68 if isProj != proj || ok != class { 69 t.Fatal("check classkind failed", name, isProj, ok) 70 } 71 } 72 73 func TestKind(t *testing.T) { 74 testKind(t, "Cat.gox", false, false) 75 testKind(t, "Cat.spx", false, true) 76 testKind(t, "main.spx", true, true) 77 testKind(t, "main.gmx", true, true) 78 testKind(t, "Cat.tspx", false, true) 79 testKind(t, "main.tspx", true, true) 80 testKind(t, "blog_yap.gox", true, true) 81 } 82 83 func TestGop(t *testing.T) { 84 var src = ` 85 println "Go+" 86 ` 87 var expect = `package main 88 89 import "fmt" 90 91 func main() { 92 fmt.Println("Go+") 93 } 94 ` 95 gopClTest(t, src, expect) 96 gopClTest(t, []byte(src), expect) 97 gopClTest(t, bytes.NewBufferString(src), expect) 98 gopClTestEx(t, `./_testdata/hello/main.gop`, nil, expect) 99 100 f, err := os.Open("./_testdata/hello/main.gop") 101 if err != nil { 102 t.Fatal("open failed", err) 103 } 104 defer f.Close() 105 gopClTest(t, f, expect) 106 } 107 108 func TestGox(t *testing.T) { 109 gopClTestEx(t, "Rect.gox", ` 110 println "Go+" 111 `, `package main 112 113 import "fmt" 114 115 type Rect struct { 116 } 117 118 func (this *Rect) Main() { 119 fmt.Println("Go+") 120 } 121 func main() { 122 } 123 `) 124 gopClTestEx(t, "Rect.gox", ` 125 var ( 126 Buffer 127 v int 128 ) 129 type Buffer struct { 130 buf []byte 131 } 132 println "Go+" 133 `, `package main 134 135 import "fmt" 136 137 type Buffer struct { 138 buf []byte 139 } 140 type Rect struct { 141 Buffer 142 v int 143 } 144 145 func (this *Rect) Main() { 146 fmt.Println("Go+") 147 } 148 func main() { 149 } 150 `) 151 gopClTestEx(t, "Rect.gox", ` 152 var ( 153 *Buffer 154 v int 155 ) 156 type Buffer struct { 157 buf []byte 158 } 159 println "Go+" 160 `, `package main 161 162 import "fmt" 163 164 type Buffer struct { 165 buf []byte 166 } 167 type Rect struct { 168 *Buffer 169 v int 170 } 171 172 func (this *Rect) Main() { 173 fmt.Println("Go+") 174 } 175 func main() { 176 } 177 `) 178 gopClTestEx(t, "Rect.gox", ` 179 import "bytes" 180 var ( 181 *bytes.Buffer 182 v int 183 ) 184 println "Go+" 185 `, `package main 186 187 import ( 188 "bytes" 189 "fmt" 190 ) 191 192 type Rect struct { 193 *bytes.Buffer 194 v int 195 } 196 197 func (this *Rect) Main() { 198 fmt.Println("Go+") 199 } 200 func main() { 201 } 202 `) 203 gopClTestEx(t, "Rect.gox", ` 204 import "bytes" 205 var ( 206 bytes.Buffer 207 v int 208 ) 209 println "Go+" 210 `, `package main 211 212 import ( 213 "bytes" 214 "fmt" 215 ) 216 217 type Rect struct { 218 bytes.Buffer 219 v int 220 } 221 222 func (this *Rect) Main() { 223 fmt.Println("Go+") 224 } 225 func main() { 226 } 227 `) 228 } 229 230 func TestBig(t *testing.T) { 231 gopClTest(t, ` 232 a := 1/2r 233 println a+1/2r 234 `, `package main 235 236 import ( 237 "fmt" 238 "github.com/goplus/gop/builtin/ng" 239 "math/big" 240 ) 241 242 func main() { 243 a := ng.Bigrat_Init__2(big.NewRat(1, 2)) 244 fmt.Println((ng.Bigrat).Gop_Add(a, ng.Bigrat_Init__2(big.NewRat(1, 2)))) 245 } 246 `) 247 } 248 249 func TestIoxLines(t *testing.T) { 250 gopClTest(t, ` 251 import "io" 252 253 var r io.Reader 254 255 for line <- lines(r) { 256 println line 257 } 258 `, `package main 259 260 import ( 261 "fmt" 262 "github.com/goplus/gop/builtin/iox" 263 "io" 264 ) 265 266 var r io.Reader 267 268 func main() { 269 for _gop_it := iox.Lines(r).Gop_Enum(); ; { 270 var _gop_ok bool 271 line, _gop_ok := _gop_it.Next() 272 if !_gop_ok { 273 break 274 } 275 fmt.Println(line) 276 } 277 } 278 `) 279 } 280 281 func TestErrorWrap(t *testing.T) { 282 gopClTest(t, ` 283 import ( 284 "strconv" 285 ) 286 287 func add(x, y string) (int, error) { 288 return strconv.Atoi(x)? + strconv.Atoi(y)?, nil 289 } 290 291 func addSafe(x, y string) int { 292 return strconv.Atoi(x)?:0 + strconv.Atoi(y)?:0 293 } 294 295 println add("100", "23")! 296 297 sum, err := add("10", "abc") 298 println sum, err 299 300 println addSafe("10", "abc") 301 `, `package main 302 303 import ( 304 "fmt" 305 "github.com/qiniu/x/errors" 306 "strconv" 307 ) 308 309 func add(x string, y string) (int, error) { 310 var _autoGo_1 int 311 { 312 var _gop_err error 313 _autoGo_1, _gop_err = strconv.Atoi(x) 314 if _gop_err != nil { 315 _gop_err = errors.NewFrame(_gop_err, "strconv.Atoi(x)", "main.gop", 7, "main.add") 316 return 0, _gop_err 317 } 318 goto _autoGo_2 319 _autoGo_2: 320 } 321 var _autoGo_3 int 322 { 323 var _gop_err error 324 _autoGo_3, _gop_err = strconv.Atoi(y) 325 if _gop_err != nil { 326 _gop_err = errors.NewFrame(_gop_err, "strconv.Atoi(y)", "main.gop", 7, "main.add") 327 return 0, _gop_err 328 } 329 goto _autoGo_4 330 _autoGo_4: 331 } 332 return _autoGo_1 + _autoGo_3, nil 333 } 334 func addSafe(x string, y string) int { 335 return func() (_gop_ret int) { 336 var _gop_err error 337 _gop_ret, _gop_err = strconv.Atoi(x) 338 if _gop_err != nil { 339 return 0 340 } 341 return 342 }() + func() (_gop_ret int) { 343 var _gop_err error 344 _gop_ret, _gop_err = strconv.Atoi(y) 345 if _gop_err != nil { 346 return 0 347 } 348 return 349 }() 350 } 351 func main() { 352 fmt.Println(func() (_gop_ret int) { 353 var _gop_err error 354 _gop_ret, _gop_err = add("100", "23") 355 if _gop_err != nil { 356 _gop_err = errors.NewFrame(_gop_err, "add(\"100\", \"23\")", "main.gop", 14, "main.main") 357 panic(_gop_err) 358 } 359 return 360 }()) 361 sum, err := add("10", "abc") 362 fmt.Println(sum, err) 363 fmt.Println(addSafe("10", "abc")) 364 } 365 `) 366 } 367 368 func TestSpx(t *testing.T) { 369 gopClTestEx(t, "main.tspx", `println "hi"`, `package main 370 371 import ( 372 "fmt" 373 "github.com/goplus/gop/cl/internal/spx" 374 ) 375 376 type MyGame struct { 377 spx.MyGame 378 } 379 380 func (this *MyGame) MainEntry() { 381 fmt.Println("hi") 382 } 383 func (this *MyGame) Main() { 384 spx.Gopt_MyGame_Main(this) 385 } 386 func main() { 387 new(MyGame).Main() 388 } 389 `) 390 gopClTestEx(t, "Cat.tspx", `println "hi"`, `package main 391 392 import ( 393 "fmt" 394 "github.com/goplus/gop/cl/internal/spx" 395 ) 396 397 type Cat struct { 398 spx.Sprite 399 *MyGame 400 } 401 type MyGame struct { 402 spx.MyGame 403 } 404 405 func (this *Cat) Main() { 406 fmt.Println("hi") 407 } 408 func (this *Cat) Classfname() string { 409 return "Cat" 410 } 411 func (this *MyGame) Main() { 412 spx.Gopt_MyGame_Main(this) 413 } 414 func main() { 415 new(MyGame).Main() 416 } 417 `) 418 } 419 420 func testFromDir(t *testing.T, relDir string) { 421 dir, err := os.Getwd() 422 if err != nil { 423 t.Fatal("Getwd failed:", err) 424 } 425 dir = path.Join(dir, relDir) 426 fis, err := os.ReadDir(dir) 427 if err != nil { 428 t.Fatal("ReadDir failed:", err) 429 } 430 for _, fi := range fis { 431 name := fi.Name() 432 if strings.HasPrefix(name, "_") { 433 continue 434 } 435 t.Run(name, func(t *testing.T) { 436 testFrom(t, name, dir+"/"+name) 437 }) 438 } 439 } 440 441 func testFrom(t *testing.T, name, dir string) { 442 data, err := ctx.BuildDir(dir) 443 if err != nil { 444 t.Fatal("BuildDir failed:", err) 445 } 446 if chk, err := os.ReadFile(filepath.Join(dir, name+".expect")); err == nil { 447 if !bytes.Equal(data, chk) { 448 t.Fatalf("-- %v output check error --\n%v\n--\n%v", name, string(data), string(chk)) 449 } 450 } 451 } 452 453 func TestFromTestdata(t *testing.T) { 454 testFromDir(t, "./_testdata") 455 } 456 457 func TestFS(t *testing.T) { 458 var expect = []byte(`package main 459 460 import "fmt" 461 462 func main() { 463 fmt.Println("Go+") 464 } 465 `) 466 data, err := ctx.BuildFSDir(fsx.Local, "./_testdata/hello") 467 if err != nil { 468 t.Fatal("build fs dir failed", err) 469 } 470 if !bytes.Equal(data, expect) { 471 t.Fatal("build fs data failed", string(data)) 472 } 473 } 474 475 func TestAst(t *testing.T) { 476 var expect = []byte(`package main 477 478 import "fmt" 479 480 func main() { 481 fmt.Println("Go+") 482 } 483 `) 484 pkg, err := ctx.ParseFSDir(fsx.Local, "./_testdata/hello") 485 if err != nil { 486 t.Fatal("parser fs dir failed", err) 487 } 488 var buf bytes.Buffer 489 err = printer.Fprint(&buf, pkg.Fset, pkg.ToAst()) 490 if err != nil { 491 t.Fatal("fprint ast error", err) 492 } 493 if !bytes.Equal(buf.Bytes(), expect) { 494 t.Fatal("build ast data failed", buf.String()) 495 } 496 } 497 498 func TestError(t *testing.T) { 499 _, err := ctx.BuildFile("main.gop", "bad code") 500 if err == nil { 501 t.Fatal("BuildFile: no error?") 502 } 503 _, err = ctx.BuildDir("./testdata/nofound") 504 if err == nil { 505 t.Fatal("BuildDir: no error?") 506 } 507 _, err = ctx.BuildFSDir(fsx.Local, "./testdata/nofound") 508 if err == nil { 509 t.Fatal("BuildDir: no error?") 510 } 511 _, err = ctx.BuildFile("main.gop", "func main()") 512 if err == nil { 513 t.Fatal("BuildFile: no error?") 514 } 515 _, err = ctx.ParseFile("main.gop", 123) 516 if err == nil { 517 t.Fatal("ParseFile: no error?") 518 } 519 _, err = ctx.ParseFile("./testdata/nofound/main.gop", nil) 520 if err == nil { 521 t.Fatal("ParseFile: no error?") 522 } 523 } 524 525 type emptyImporter struct { 526 } 527 528 func (i *emptyImporter) Import(path string) (*types.Package, error) { 529 return nil, fmt.Errorf("not found %v", path) 530 } 531 532 func TestContext(t *testing.T) { 533 ctx := build.NewContext(&emptyImporter{}, nil) 534 _, err := ctx.BuildFile("main.gop", `import "fmt"; fmt.Println "Go+"`) 535 if err == nil { 536 t.Fatal("BuildFile: no error?") 537 } 538 }