github.com/gotranspile/cxgo@v0.3.7/compile_test.go (about)

     1  package cxgo
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"os/exec"
     9  	"path/filepath"
    10  	"testing"
    11  
    12  	"github.com/stretchr/testify/require"
    13  
    14  	"github.com/gotranspile/cxgo/libs"
    15  	"github.com/gotranspile/cxgo/types"
    16  )
    17  
    18  func gccCompile(t testing.TB, out, cfile string) {
    19  	var buf bytes.Buffer
    20  	cmd := exec.Command("gcc", "-O0", "-o", out, cfile)
    21  	cmd.Stdout = &buf
    22  	cmd.Stderr = &buf
    23  	err := cmd.Run()
    24  	if err != nil {
    25  		t.Fatalf("gcc compilation failed: %v\n%s", err, buf.String())
    26  	}
    27  }
    28  
    29  func gccCompileAndExec(t testing.TB, dir, cfile string) progOut {
    30  	cbin := filepath.Join(dir, "out")
    31  	gccCompile(t, cbin, cfile)
    32  	return progExecute(dir, cbin)
    33  }
    34  
    35  func goCompile(t testing.TB, out, dir string) {
    36  	var buf bytes.Buffer
    37  	cmd := exec.Command("go", "build", "-o", out, ".")
    38  	cmd.Dir = dir
    39  	cmd.Stdout = &buf
    40  	cmd.Stderr = &buf
    41  	err := cmd.Run()
    42  	if err != nil {
    43  		t.Fatalf("go compilation failed: %v\n%s", err, buf.String())
    44  	}
    45  }
    46  
    47  func goCompileAndExec(t testing.TB, dir string) progOut {
    48  	gobin := filepath.Join(dir, "out")
    49  	goCompile(t, gobin, dir)
    50  	return progExecute(dir, gobin)
    51  }
    52  
    53  func goTranspileAndExec(t testing.TB, cxgo, dir string, cfile string) progOut {
    54  	goProject(t, dir, cxgo)
    55  	gofile := filepath.Join(dir, "main.go")
    56  	env := libs.NewEnv(types.Config32())
    57  	err := Translate(filepath.Dir(cfile), cfile, dir, env, Config{
    58  		Package:     "main",
    59  		GoFile:      gofile,
    60  		MaxDecls:    -1,
    61  		ForwardDecl: false,
    62  	})
    63  	require.NoError(t, err)
    64  	goProjectMod(t, dir)
    65  	gosrc, err := ioutil.ReadFile(gofile)
    66  	require.NoError(t, err)
    67  	t.Logf("// === Go source ===\n%s", string(gosrc))
    68  	return goCompileAndExec(t, dir)
    69  }
    70  
    71  type progOut struct {
    72  	Code int
    73  	Err  error
    74  	Out  string
    75  }
    76  
    77  func execInDir(wd string, bin string, args ...string) error {
    78  	cmd := exec.Command(bin, args...)
    79  	cmd.Dir = wd
    80  	return cmd.Run()
    81  }
    82  
    83  func progExecute(wd, bin string) progOut {
    84  	var buf bytes.Buffer
    85  	cmd := exec.Command(bin)
    86  	cmd.Dir = wd
    87  	cmd.Stdout = &buf
    88  	cmd.Stderr = &buf
    89  	err := cmd.Run()
    90  	out := progOut{
    91  		Err: err,
    92  		Out: buf.String(),
    93  	}
    94  	if e, ok := err.(*exec.ExitError); ok && e.Exited() {
    95  		out.Code = e.ExitCode()
    96  		out.Err = nil
    97  	}
    98  	return out
    99  }
   100  
   101  func goProject(t testing.TB, out, cxgo string) {
   102  	cxgo, err := filepath.Abs(cxgo)
   103  	require.NoError(t, err)
   104  
   105  	err = os.MkdirAll(out, 0755)
   106  	require.NoError(t, err)
   107  
   108  	gomod := fmt.Sprintf(`module main
   109  go 1.18
   110  require (
   111  	github.com/gotranspile/cxgo v0.0.0-local
   112  )
   113  replace github.com/gotranspile/cxgo v0.0.0-local => %s`, cxgo)
   114  
   115  	err = ioutil.WriteFile(filepath.Join(out, "go.mod"), []byte(gomod), 0644)
   116  	require.NoError(t, err)
   117  
   118  	// allows running go mod tidy without having other source files and still keep require above
   119  	err = ioutil.WriteFile(filepath.Join(out, "dummy.go"), []byte(`
   120  package main
   121  
   122  import _ "github.com/gotranspile/cxgo/runtime/libc"
   123  `), 0644)
   124  	require.NoError(t, err)
   125  }
   126  
   127  func goProjectMod(t testing.TB, out string) {
   128  	err := execInDir(out, "go", "mod", "tidy")
   129  	require.NoError(t, err)
   130  }