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