github.com/FTwOoO/c4go@v0.0.0-20200324072034-78f7ddb713bb/other_test.go (about)

     1  package main
     2  
     3  import (
     4  	"archive/zip"
     5  	"bufio"
     6  	"bytes"
     7  	"fmt"
     8  	"io"
     9  	"io/ioutil"
    10  	"net/http"
    11  	"os"
    12  	"os/exec"
    13  	"path/filepath"
    14  	"strconv"
    15  	"strings"
    16  	"sync"
    17  	"sync/atomic"
    18  	"testing"
    19  
    20  	"github.com/FTwOoO/c4go/program"
    21  )
    22  
    23  func getFileList(prefix, gitSource string) (fileList []string, err error) {
    24  	var (
    25  		buildFolder = "testdata"
    26  		gitFolder   = "git-source"
    27  		separator   = string(os.PathSeparator)
    28  	)
    29  
    30  	// Create build folder
    31  	folder := buildFolder + separator + gitFolder + separator + prefix + separator
    32  	if _, err = os.Stat(folder); os.IsNotExist(err) {
    33  		err = os.MkdirAll(folder, os.ModePerm)
    34  		if err != nil {
    35  			err = fmt.Errorf("cannot create folder %v . %v", folder, err)
    36  			return
    37  		}
    38  
    39  		// clone git repository
    40  		args := []string{"clone", gitSource, folder}
    41  		err = exec.Command("git", args...).Run()
    42  		if err != nil {
    43  			err = fmt.Errorf("cannot clone git repository with args `%v`: %v",
    44  				args, err)
    45  			return
    46  		}
    47  	}
    48  
    49  	// find all C source files
    50  	err = filepath.Walk(folder, func(path string, f os.FileInfo, err error) error {
    51  		if strings.HasSuffix(strings.ToLower(f.Name()), ".c") {
    52  			fileList = append(fileList, path)
    53  		}
    54  		return nil
    55  	})
    56  	if err != nil {
    57  		err = fmt.Errorf("cannot walk: %v", err)
    58  		return
    59  	}
    60  
    61  	return
    62  }
    63  
    64  func TestBookSources(t *testing.T) {
    65  	// test create not for TRAVIS CI
    66  	if os.Getenv("TRAVIS") == "true" {
    67  		t.Skip()
    68  	}
    69  
    70  	defer func() {
    71  		if r := recover(); r != nil {
    72  			t.Errorf("Panic is not acceptable: %v", r)
    73  		}
    74  	}()
    75  
    76  	tcs := []struct {
    77  		prefix         string
    78  		gitSource      string
    79  		ignoreFileList []string
    80  	}{
    81  		// {
    82  		// 	prefix:    "brainfuck",
    83  		// 	gitSource: "https://github.com/kgabis/brainfuck-c.git",
    84  		// },
    85  		// TODO : some travis haven`t enought C libraries
    86  		// {
    87  		// 	prefix:    "tiny-web-server",
    88  		// 	gitSource: "https://github.com/shenfeng/tiny-web-server.git",
    89  		// },
    90  		{
    91  			prefix:         "c-testsuite",
    92  			gitSource:      "https://github.com/c-testsuite/c-testsuite.git",
    93  			ignoreFileList: []string{},
    94  		},
    95  		{
    96  			prefix:    "VasielBook",
    97  			gitSource: "https://github.com/olegbukatchuk/book-c-the-examples-and-tasks.git",
    98  			ignoreFileList: []string{
    99  				"1.13/main.c",
   100  				"1.6/main.c",
   101  				"5.9/main.c",
   102  				"3.19/main.c",
   103  				"3.17/main.c",
   104  			},
   105  		},
   106  		{
   107  			prefix:    "KR",
   108  			gitSource: "https://github.com/KushalP/k-and-r.git",
   109  			ignoreFileList: []string{
   110  				"4.1-1.c",
   111  				"4-11.c",
   112  				"1.9-1.c",
   113  				"1.10-1.c",
   114  				"1-24.c",
   115  				"1-17.c",
   116  				"1-16.c",
   117  				"4-10.c",
   118  			},
   119  		},
   120  		//{
   121  		//	prefix:    "KochanBook",
   122  		//	gitSource: "https://github.com/eugenetriguba/programming-in-c.git",
   123  		//	ignoreFileList: []string{
   124  		//		"5.9d.c",
   125  		//		"5.9c.c",
   126  		//	},
   127  		//},
   128  		{
   129  			prefix:    "DeitelBook",
   130  			gitSource: "https://github.com/Emmetttt/C-Deitel-Book.git",
   131  			ignoreFileList: []string{
   132  				"E5.45.C",
   133  				"06.14_const_type_qualifier.C",
   134  				"E7.17.C",
   135  			},
   136  		},
   137  	}
   138  
   139  	chFile := make(chan string, 10)
   140  	var wg sync.WaitGroup
   141  	var amountWarnings int32
   142  
   143  	for i := 0; i < 10; i++ {
   144  		wg.Add(1)
   145  		go func() {
   146  			defer wg.Done()
   147  			for f := range chFile {
   148  				file := f
   149  				// run test
   150  				t.Run(file, func(t *testing.T) {
   151  					file = strings.TrimSpace(file)
   152  					goFile := file + ".go"
   153  					args := DefaultProgramArgs()
   154  					args.inputFiles = []string{file}
   155  					args.outputFile = goFile
   156  					args.state = StateTranspile
   157  					args.verbose = false
   158  
   159  					if err := Start(args); err != nil {
   160  						t.Fatalf("Cannot transpile `%v`: %v", args, err)
   161  					}
   162  
   163  					// logging warnings
   164  					var err error
   165  					var logs []string
   166  					logs, err = getLogs(goFile)
   167  					if err != nil {
   168  						t.Errorf("Error in `%v`: %v", goFile, err)
   169  					}
   170  					for _, log := range logs {
   171  						t.Logf("`%v`:%v\n", file, log)
   172  					}
   173  
   174  					// go build testing
   175  					if len(logs) == 0 {
   176  						cmd := exec.Command("go", "build",
   177  							"-o", goFile+".out", goFile)
   178  						cmdOutput := &bytes.Buffer{}
   179  						cmdErr := &bytes.Buffer{}
   180  						cmd.Stdout = cmdOutput
   181  						cmd.Stderr = cmdErr
   182  						err = cmd.Run()
   183  						if err != nil {
   184  							t.Logf("Go build test `%v` : err = %v\n%v",
   185  								file, err, cmdErr.String())
   186  							atomic.AddInt32(&amountWarnings, 1)
   187  						}
   188  					}
   189  
   190  					// warning counter
   191  					atomic.AddInt32(&amountWarnings, int32(len(logs)))
   192  				})
   193  			}
   194  		}()
   195  	}
   196  
   197  	for _, tc := range tcs {
   198  		fileList, err := getFileList(tc.prefix, tc.gitSource)
   199  		if err != nil {
   200  			t.Fatal(err)
   201  		}
   202  		for _, file := range fileList {
   203  			// ignore list of sources
   204  			var ignored bool
   205  			for _, ignore := range tc.ignoreFileList {
   206  				if strings.Contains(strings.ToLower(file), strings.ToLower(ignore)) {
   207  					ignored = true
   208  				}
   209  			}
   210  			if ignored {
   211  				continue
   212  			}
   213  
   214  			chFile <- file
   215  		}
   216  	}
   217  
   218  	close(chFile)
   219  	wg.Wait()
   220  
   221  	t.Logf("Amount warnings summary : %v", amountWarnings)
   222  }
   223  
   224  func getLogs(goFile string) (logs []string, err error) {
   225  	file, err := os.Open(goFile)
   226  	if err != nil {
   227  		return
   228  	}
   229  	defer file.Close()
   230  
   231  	scanner := bufio.NewScanner(file)
   232  	for scanner.Scan() {
   233  		line := scanner.Text()
   234  
   235  		// ignore
   236  		// Warning (*ast.TranslationUnitDecl):  :0 :cannot transpileRecordDecl `__WAIT_STATUS`. could not determine the size of type `union __WAIT_STATUS` for that reason: Cannot determine sizeof : |union __WAIT_STATUS|. err = Cannot canculate `union` sizeof for `string`. Cannot determine sizeof : |union wait *|. err = error in union
   237  		if strings.Contains(line, "union __WAIT_STATUS") {
   238  			continue
   239  		}
   240  
   241  		if strings.Contains(line, "/"+"/") && strings.Contains(line, "AST") {
   242  			logs = append(logs, line)
   243  		}
   244  		if strings.HasPrefix(line, "/"+"/ Warning") {
   245  			logs = append(logs, line)
   246  		}
   247  	}
   248  
   249  	err = scanner.Err()
   250  	return
   251  }
   252  
   253  func TestFrame3dd(t *testing.T) {
   254  	folder := "./testdata/git-source/frame3dd/"
   255  
   256  	// Create build folder
   257  	if _, err := os.Stat(folder); os.IsNotExist(err) {
   258  		err = os.MkdirAll(folder, os.ModePerm)
   259  		if err != nil {
   260  			t.Fatalf("Cannot create folder %v . %v", folder, err)
   261  		}
   262  
   263  		// clone git repository
   264  
   265  		args := []string{"clone", "-b", "Debug2", "https://github.com/FTwOoO/History_frame3DD.git", folder}
   266  		err = exec.Command("git", args...).Run()
   267  		if err != nil {
   268  			t.Fatalf("Cannot clone git repository with args `%v`: %v", args, err)
   269  		}
   270  	}
   271  
   272  	args := DefaultProgramArgs()
   273  	args.inputFiles = []string{
   274  		folder + "src/main.c",
   275  		folder + "src/frame3dd.c",
   276  		folder + "src/frame3dd_io.c",
   277  		folder + "src/coordtrans.c",
   278  		folder + "src/eig.c",
   279  		folder + "src/HPGmatrix.c",
   280  		folder + "src/HPGutil.c",
   281  		folder + "src/NRutil.c",
   282  	}
   283  	args.clangFlags = []string{
   284  		"-I" + folder + "viewer",
   285  		"-I" + folder + "microstran",
   286  	}
   287  	args.outputFile = folder + "src/main.go"
   288  	args.state = StateTranspile
   289  	args.verbose = false
   290  
   291  	if err := Start(args); err != nil {
   292  		t.Fatalf("Cannot transpile `%v`: %v", args, err)
   293  	}
   294  
   295  	// print logs
   296  	ls, err := getLogs(folder + "src/main.go")
   297  	if err != nil {
   298  		t.Fatalf("Cannot show logs: %v", err)
   299  	}
   300  	for _, l := range ls {
   301  		t.Log(l)
   302  	}
   303  
   304  	cmd := exec.Command("go", "build", "-o", folder+"src/frame3dd",
   305  		args.outputFile)
   306  	var stdout, stderr bytes.Buffer
   307  	cmd.Stdout = &stdout
   308  	cmd.Stderr = &stderr
   309  	err = cmd.Run()
   310  	if err != nil {
   311  		parseError(t, stderr.String())
   312  		t.Errorf("cmd.Run() failed with %s : %v\n", err, stderr.String())
   313  	}
   314  }
   315  
   316  func TestCsparse(t *testing.T) {
   317  	folder := "./testdata/git-source/csparse/"
   318  
   319  	//	Create build folder
   320  	if _, err := os.Stat(folder); os.IsNotExist(err) {
   321  		err = os.MkdirAll(folder, os.ModePerm)
   322  		if err != nil {
   323  			t.Fatalf("Cannot create folder %v . %v", folder, err)
   324  		}
   325  
   326  		// download file
   327  		t.Logf("Download files")
   328  		err := copyFile(
   329  			"./tests/vendor/csparce/csparse.h",
   330  			folder+"csparse.h",
   331  		)
   332  		if err != nil {
   333  			t.Fatalf("Cannot download : %v", err)
   334  		}
   335  		err = copyFile(
   336  			"./tests/vendor/csparce/csparse.c",
   337  			folder+"csparse.c",
   338  		)
   339  		if err != nil {
   340  			t.Fatalf("cannot download : %v", err)
   341  		}
   342  		err = copyFile(
   343  			"./tests/vendor/csparce/csparse_demo1.c",
   344  			folder+"csparse_demo1.c",
   345  		)
   346  		if err != nil {
   347  			t.Fatalf("Cannot download : %v", err)
   348  		}
   349  		err = copyFile(
   350  			"./tests/vendor/csparce/kershaw.st",
   351  			folder+"kershaw.st",
   352  		)
   353  		if err != nil {
   354  			t.Fatalf("cannot download : %v", err)
   355  		}
   356  	}
   357  
   358  	args := DefaultProgramArgs()
   359  	args.inputFiles = []string{
   360  		folder + "csparse.c",
   361  		folder + "csparse_demo1.c",
   362  	}
   363  	args.clangFlags = []string{}
   364  	args.outputFile = folder + "main.go"
   365  	args.state = StateTranspile
   366  	args.verbose = false
   367  
   368  	if err := Start(args); err != nil {
   369  		t.Fatalf("Cannot transpile `%v`: %v", args, err)
   370  	}
   371  
   372  	//	print logs
   373  	ls, err := getLogs(folder + "main.go")
   374  	if err != nil {
   375  		t.Fatalf("Cannot show logs: %v", err)
   376  	}
   377  	for _, l := range ls {
   378  		t.Log(l)
   379  	}
   380  
   381  	cmd := exec.Command("go", "build", "-o", folder+"csparse",
   382  		args.outputFile)
   383  	var stdout, stderr bytes.Buffer
   384  	cmd.Stdout = &stdout
   385  	cmd.Stderr = &stderr
   386  	err = cmd.Run()
   387  	if err != nil {
   388  		t.Logf("cmd.Run() failed with %s : %v\n", err, stderr.String())
   389  	}
   390  }
   391  
   392  func parseError(t *testing.T, str string) {
   393  	// Example:
   394  	// testdata/git-source/triangle/main.go:2478:41: invalid operation: (operator & not defined on slice)
   395  	lines := strings.Split(str, "\n")
   396  	codes := map[string][]string{}
   397  	for _, line := range lines {
   398  		line = strings.TrimSpace(line)
   399  		index := strings.Index(line, ":")
   400  		if index < 0 {
   401  			continue
   402  		}
   403  		filename := line[:index]
   404  		if _, err := os.Stat(filename); os.IsNotExist(err) {
   405  			// filename does not exist
   406  			continue
   407  		}
   408  		if _, ok := codes[filename]; !ok {
   409  			dat, err := ioutil.ReadFile(filename)
   410  			if err != nil {
   411  				continue
   412  			}
   413  			codes[filename] = strings.Split(string(dat), "\n")
   414  		}
   415  		indexLine := strings.Index(line[index+1:], ":")
   416  		if indexLine < 0 {
   417  			continue
   418  		}
   419  		if s, err := strconv.Atoi(line[index+1 : index+indexLine+1]); err == nil {
   420  			t.Logf("Code line %s: %s\n", line[index+1:index+indexLine+1], codes[filename][s-1])
   421  		}
   422  	}
   423  }
   424  
   425  // unzip will decompress a zip archive, moving all files and folders
   426  // within the zip file (parameter 1) to an output directory (parameter 2).
   427  func unzip(src string, dest string) ([]string, error) {
   428  
   429  	var filenames []string
   430  
   431  	r, err := zip.OpenReader(src)
   432  	if err != nil {
   433  		return filenames, err
   434  	}
   435  	defer r.Close()
   436  
   437  	for _, f := range r.File {
   438  
   439  		rc, err := f.Open()
   440  		if err != nil {
   441  			return filenames, err
   442  		}
   443  		defer rc.Close()
   444  
   445  		// Store filename/path for returning and using later on
   446  		fpath := filepath.Join(dest, f.Name)
   447  
   448  		// Check for ZipSlip. More Info: http://bit.ly/2MsjAWE
   449  		if !strings.HasPrefix(fpath, filepath.Clean(dest)+string(os.PathSeparator)) {
   450  			return filenames, fmt.Errorf("%s: illegal file path", fpath)
   451  		}
   452  
   453  		filenames = append(filenames, fpath)
   454  
   455  		if f.FileInfo().IsDir() {
   456  
   457  			// Make Folder
   458  			os.MkdirAll(fpath, os.ModePerm)
   459  
   460  		} else {
   461  
   462  			// Make File
   463  			if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
   464  				return filenames, err
   465  			}
   466  
   467  			outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
   468  			if err != nil {
   469  				return filenames, err
   470  			}
   471  
   472  			_, err = io.Copy(outFile, rc)
   473  
   474  			// Close the file without defer to close before next iteration of loop
   475  			outFile.Close()
   476  
   477  			if err != nil {
   478  				return filenames, err
   479  			}
   480  
   481  		}
   482  	}
   483  	return filenames, nil
   484  }
   485  
   486  // downloadFile will download a url to a local file. It's efficient because it will
   487  // write as it downloads and not load the whole file into memory.
   488  func downloadFile(filepath string, url string) error {
   489  
   490  	// Create the file
   491  	out, err := os.Create(filepath)
   492  	if err != nil {
   493  		err = fmt.Errorf("cannot create %v", err)
   494  		return err
   495  	}
   496  	defer out.Close()
   497  
   498  	// Get the data
   499  	resp, err := http.Get(url)
   500  	if err != nil {
   501  		return err
   502  	}
   503  	defer resp.Body.Close()
   504  
   505  	// Write the body to file
   506  	_, err = io.Copy(out, resp.Body)
   507  	if err != nil {
   508  		return err
   509  	}
   510  
   511  	return nil
   512  }
   513  
   514  func copyFile(sourceFile, destinationFile string) (err error) {
   515  	input, err := ioutil.ReadFile(sourceFile)
   516  	if err != nil {
   517  		return
   518  	}
   519  
   520  	err = ioutil.WriteFile(destinationFile, input, 0644)
   521  	if err != nil {
   522  		return
   523  	}
   524  
   525  	return nil
   526  }
   527  
   528  func TestMultifiles(t *testing.T) {
   529  	// test create not for TRAVIS CI
   530  	if os.Getenv("TRAVIS") == "true" {
   531  		t.Skip()
   532  	}
   533  
   534  	type fs struct {
   535  		input  []string
   536  		clang  []string
   537  		output string
   538  	}
   539  	tcs := []struct {
   540  		prefix    string
   541  		gitSource string
   542  		files     []fs
   543  	}{
   544  		{
   545  			prefix:    "parg",
   546  			gitSource: "https://github.com/jibsen/parg.git",
   547  			files: []fs{
   548  				{
   549  					input: []string{"testdata/git-source/parg/parg.c"},
   550  					clang: []string{
   551  						"-Itestdata/git-source/parg/",
   552  					},
   553  					output: "testdata/git-source/parg/parg.go",
   554  				},
   555  				{
   556  					input: []string{
   557  						"testdata/git-source/parg/test/test_parg.c",
   558  					},
   559  					clang: []string{
   560  						"-Itestdata/git-source/parg/",
   561  					},
   562  					output: "testdata/git-source/parg/test/test.go",
   563  				},
   564  			},
   565  		},
   566  		{
   567  			prefix:    "stmr.c",
   568  			gitSource: "https://github.com/wooorm/stmr.c",
   569  			files: []fs{
   570  				{
   571  					input:  []string{"testdata/git-source/stmr.c/stmr.c"},
   572  					output: "testdata/git-source/stmr.c/stmr.go",
   573  				},
   574  			},
   575  		},
   576  		{
   577  			prefix:    "tinyexpr",
   578  			gitSource: "https://github.com/codeplea/tinyexpr.git",
   579  			files: []fs{
   580  				{
   581  					input:  []string{"testdata/git-source/tinyexpr/tinyexpr.c"},
   582  					output: "testdata/git-source/tinyexpr/tinyexpr.go",
   583  				},
   584  			},
   585  		},
   586  	}
   587  
   588  	for _, tc := range tcs {
   589  		fileList, err := getFileList(tc.prefix, tc.gitSource)
   590  		if err != nil {
   591  			t.Fatal(err)
   592  		}
   593  		t.Log(fileList)
   594  
   595  		for _, f := range tc.files {
   596  			t.Run(fmt.Sprintf("%v", f), func(t *testing.T) {
   597  				args := DefaultProgramArgs()
   598  				args.inputFiles = f.input
   599  				args.clangFlags = f.clang
   600  				args.outputFile = f.output
   601  				args.state = StateTranspile
   602  				args.verbose = false
   603  
   604  				if err := Start(args); err != nil {
   605  					t.Fatalf("Cannot transpile `%v`: %v", args, err)
   606  				}
   607  
   608  				// logging warnings
   609  				var err error
   610  				var logs []string
   611  				logs, err = getLogs(f.output)
   612  				if err != nil {
   613  					t.Errorf("Error in `%v`: %v", f.output, err)
   614  				}
   615  				for _, log := range logs {
   616  					t.Logf("`%v`:%v\n", f.output, log)
   617  				}
   618  			})
   619  		}
   620  	}
   621  }
   622  
   623  func TestKiloEditor(t *testing.T) {
   624  
   625  	prefix := "kilo editor"
   626  	gitSource := "https://github.com/antirez/kilo.git"
   627  
   628  	fileList, err := getFileList(prefix, gitSource)
   629  	if err != nil {
   630  		t.Fatal(err)
   631  	}
   632  
   633  	if len(fileList) != 1 {
   634  		t.Fatalf("fileList is not correct: %v", fileList)
   635  	}
   636  
   637  	if !strings.Contains(fileList[0], "kilo.c") {
   638  		t.Fatalf("filename is not correct: %v", fileList[0])
   639  	}
   640  
   641  	goFile := fileList[0] + ".go"
   642  	args := DefaultProgramArgs()
   643  	args.inputFiles = []string{fileList[0]}
   644  	args.outputFile = goFile
   645  	args.state = StateTranspile
   646  	args.verbose = false
   647  
   648  	if err := Start(args); err != nil {
   649  		t.Fatalf("Cannot transpile `%v`: %v", args, err)
   650  	}
   651  
   652  	// warning is not acceptable
   653  	dat, err := ioutil.ReadFile(goFile)
   654  	if err != nil {
   655  		t.Fatal(err)
   656  	}
   657  
   658  	if bytes.Contains(dat, []byte(program.WarningMessage)) {
   659  		t.Fatalf("find warning message")
   660  	}
   661  
   662  	// calculate amount unsafe operations
   663  	unsafeLimit := 29
   664  	uintptrLimit := 18
   665  	if count := bytes.Count(dat, []byte("unsafe.Pointer")); count > unsafeLimit {
   666  		t.Fatalf("too much unsafe operations: %d", count)
   667  	} else {
   668  		t.Logf("amount unsafe operations: %d", count)
   669  	}
   670  	if count := bytes.Count(dat, []byte("uintptr")); count > uintptrLimit {
   671  		t.Fatalf("too much uintptr operations: %d", count)
   672  	} else {
   673  		t.Logf("amount uintptr operations: %d", count)
   674  	}
   675  
   676  	cmd := exec.Command("go", "build",
   677  		"-o", goFile+".app",
   678  		"-gcflags", "-e",
   679  		goFile)
   680  	cmdOutput := &bytes.Buffer{}
   681  	cmdErr := &bytes.Buffer{}
   682  	cmd.Stdout = cmdOutput
   683  	cmd.Stderr = cmdErr
   684  	err = cmd.Run()
   685  	if err != nil {
   686  		t.Fatalf("Go build test `%v` : err = %v\n%v",
   687  			goFile, err, cmdErr.String())
   688  	}
   689  }
   690  
   691  func TestTinn(t *testing.T) {
   692  
   693  	prefix := "Tinn"
   694  	gitSource := "https://github.com/glouw/tinn.git"
   695  
   696  	fileList, err := getFileList(prefix, gitSource)
   697  	if err != nil {
   698  		t.Fatal(err)
   699  	}
   700  
   701  	goFile := fileList[0] + ".go"
   702  	args := DefaultProgramArgs()
   703  	args.inputFiles = fileList
   704  	args.outputFile = goFile
   705  	args.state = StateTranspile
   706  	args.verbose = false
   707  
   708  	if err := Start(args); err != nil {
   709  		t.Fatalf("Cannot transpile `%v`: %v", args, err)
   710  	}
   711  
   712  	// warning is not acceptable
   713  	dat, err := ioutil.ReadFile(goFile)
   714  	if err != nil {
   715  		t.Fatal(err)
   716  	}
   717  
   718  	if bytes.Contains(dat, []byte(program.WarningMessage)) {
   719  		t.Fatalf("find warning message")
   720  	}
   721  
   722  	// calculate amount unsafe operations
   723  	unsafeLimit := 15
   724  	uintptrLimit := 15
   725  	if count := bytes.Count(dat, []byte("unsafe.Pointer")); count > unsafeLimit {
   726  		t.Fatalf("too much unsafe operations: %d", count)
   727  	} else {
   728  		t.Logf("amount unsafe operations: %d", count)
   729  	}
   730  	if count := bytes.Count(dat, []byte("uintptr")); count > uintptrLimit {
   731  		t.Fatalf("too much uintptr operations: %d", count)
   732  	} else {
   733  		t.Logf("amount uintptr operations: %d", count)
   734  	}
   735  
   736  	cmd := exec.Command("go", "build",
   737  		// fix /usr/local/go/pkg/tool/linux_amd64/link:
   738  		// running gcc failed:
   739  		"-a",
   740  		"-o", goFile+".app",
   741  		"-gcflags", "-e",
   742  		goFile)
   743  	cmdOutput := &bytes.Buffer{}
   744  	cmdErr := &bytes.Buffer{}
   745  	cmd.Stdout = cmdOutput
   746  	cmd.Stderr = cmdErr
   747  	err = cmd.Run()
   748  	if err != nil {
   749  		t.Fatalf("Go build test `%v` : err = %v\n%v",
   750  			goFile, err, cmdErr.String())
   751  	}
   752  
   753  	// wget http://archive.ics.uci.edu/ml/machine-learning-databases/semeion/semeion.data
   754  	index := strings.LastIndex(fileList[0], "/")
   755  	filepath := fileList[0][:index+1]
   756  
   757  	currentDir, err := os.Getwd()
   758  	if err != nil {
   759  		t.Fatal(err)
   760  	}
   761  	os.Chdir(filepath)
   762  	defer func() {
   763  		os.Chdir(currentDir)
   764  	}()
   765  
   766  	if err := downloadFile(filepath+"semeion.data", "http://archive.ics.uci.edu/ml/machine-learning-databases/semeion/semeion.data"); err != nil {
   767  		t.Fatalf("%v", err)
   768  	}
   769  
   770  	cmd = exec.Command("./Tinn.c.go.app")
   771  	cmdOutput = &bytes.Buffer{}
   772  	cmdErr = &bytes.Buffer{}
   773  	cmd.Stdout = cmdOutput
   774  	cmd.Stderr = cmdErr
   775  	err = cmd.Run()
   776  	if err != nil {
   777  		t.Fatalf("Go run `%v` : err = %v\n%v\n%v",
   778  			goFile, err, cmdOutput.String(), cmdErr.String())
   779  	}
   780  	t.Logf("%s", cmdOutput.String())
   781  
   782  	// TODO : add result compare
   783  }
   784  
   785  func TestSpringerproblem(t *testing.T) {
   786  
   787  	prefix := "Springerproblem"
   788  	gitSource := "https://github.com/carstenhag/springerproblem.git"
   789  
   790  	fileList, err := getFileList(prefix, gitSource)
   791  	if err != nil {
   792  		t.Fatal(err)
   793  	}
   794  
   795  	goFile := fileList[0] + ".go"
   796  	args := DefaultProgramArgs()
   797  	args.inputFiles = fileList
   798  	args.outputFile = goFile
   799  	args.state = StateTranspile
   800  	args.verbose = false
   801  
   802  	if err := Start(args); err != nil {
   803  		t.Fatalf("Cannot transpile `%v`: %v", args, err)
   804  	}
   805  
   806  	// warning is not acceptable
   807  	dat, err := ioutil.ReadFile(goFile)
   808  	if err != nil {
   809  		t.Fatal(err)
   810  	}
   811  
   812  	if bytes.Contains(dat, []byte(program.WarningMessage)) {
   813  		t.Fatalf("find warning message")
   814  	}
   815  
   816  	// calculate amount unsafe operations
   817  	unsafeLimit := 5
   818  	uintptrLimit := 2
   819  	if count := bytes.Count(dat, []byte("unsafe.Pointer")); count > unsafeLimit {
   820  		t.Fatalf("too much unsafe operations: %d", count)
   821  	} else {
   822  		t.Logf("amount unsafe operations: %d", count)
   823  	}
   824  	if count := bytes.Count(dat, []byte("uintptr")); count > uintptrLimit {
   825  		t.Fatalf("too much uintptr operations: %d", count)
   826  	} else {
   827  		t.Logf("amount uintptr operations: %d", count)
   828  	}
   829  
   830  	cmd := exec.Command("go", "build",
   831  		"-o", goFile+".app",
   832  		"-gcflags", "-e",
   833  		goFile)
   834  	cmdOutput := &bytes.Buffer{}
   835  	cmdErr := &bytes.Buffer{}
   836  	cmd.Stdout = cmdOutput
   837  	cmd.Stderr = cmdErr
   838  	err = cmd.Run()
   839  	if err != nil {
   840  		t.Fatalf("Go build test `%v` : err = %v\n%v",
   841  			goFile, err, cmdErr.String())
   842  	}
   843  
   844  	index := strings.LastIndex(fileList[0], "/")
   845  	filepath := fileList[0][:index+1]
   846  	os.Chdir(filepath)
   847  
   848  	cmd = exec.Command("./main.c.go.app")
   849  	cmdOutput = &bytes.Buffer{}
   850  	cmdErr = &bytes.Buffer{}
   851  	cmd.Stdout = cmdOutput
   852  	cmd.Stdin = bytes.NewBuffer([]byte("1\n12\n12\n\n\n\n"))
   853  	cmd.Stderr = cmdErr
   854  	err = cmd.Run()
   855  	if err != nil {
   856  		t.Fatalf("Go run `%v` : err = %v\n%v\n%v",
   857  			goFile, err, cmdOutput.String(), cmdErr.String())
   858  	}
   859  	t.Logf("%s", cmdOutput.String())
   860  
   861  	// TODO : add result compare
   862  }