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  }