github.com/jmigpin/editor@v1.6.0/util/testutil/txtar.go (about)

     1  package testutil
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"path/filepath"
     7  	"testing"
     8  
     9  	"github.com/jmigpin/editor/util/pathutil"
    10  	"golang.org/x/tools/txtar"
    11  )
    12  
    13  func ParseTxtar(src []byte, filename string) *Archive {
    14  	tar := txtar.Parse(src)
    15  
    16  	ar := &Archive{}
    17  	ar.Filename = filename
    18  	ar.Tar = tar
    19  
    20  	line := countLines(tar.Comment)
    21  	for _, f := range tar.Files {
    22  		line++ // file header line
    23  		ar.Lines = append(ar.Lines, line)
    24  		line += countLines(f.Data)
    25  	}
    26  	return ar
    27  }
    28  
    29  //----------
    30  
    31  type Archive struct {
    32  	Tar      *txtar.Archive
    33  	Filename string // for errors
    34  	Lines    []int  // Tar.Files[] line position in src
    35  }
    36  
    37  func (ar *Archive) Error(err error, i int) error {
    38  	return fmt.Errorf("%s:%d: %w", ar.Filename, ar.Lines[i]+1, err)
    39  }
    40  
    41  //----------
    42  //----------
    43  //----------
    44  
    45  func RunArchive2(t *testing.T, ar *Archive,
    46  	fn func(t2 *testing.T, name string, input, output []byte) error,
    47  ) {
    48  	RunArchive(t, ar, []string{".in", ".out"},
    49  		func(t2 *testing.T, name string, data [][]byte) error {
    50  			return fn(t2, name, data[0], data[1])
    51  		},
    52  	)
    53  }
    54  
    55  // Expects n files named in filesExts args
    56  func RunArchive(t *testing.T, ar *Archive, filesExts []string,
    57  	fn func(t2 *testing.T, name string, datas [][]byte) error,
    58  ) {
    59  	// map files
    60  	fm := map[string]txtar.File{}
    61  	for _, file := range ar.Tar.Files {
    62  		if _, ok := fm[file.Name]; ok {
    63  			t.Fatalf("file already defined: %v", file.Name)
    64  		}
    65  		fm[file.Name] = file
    66  	}
    67  
    68  	for fi, file := range ar.Tar.Files {
    69  		// get data
    70  		datas := [][]byte{}
    71  		for i := 0; i < len(filesExts); i++ {
    72  			ext := filesExts[i]
    73  			fname := pathutil.ReplaceExt(file.Name, ext)
    74  
    75  			// run only files that match the first ext
    76  			if i == 0 {
    77  				if fname != file.Name {
    78  					break
    79  				}
    80  			}
    81  
    82  			f, ok := fm[fname]
    83  			if !ok {
    84  				// show warning only for files after first
    85  				if i > 0 {
    86  					t.Logf("warning: missing %q for %v", ext, file.Name)
    87  				}
    88  				break
    89  			}
    90  			datas = append(datas, f.Data)
    91  		}
    92  		if len(datas) != len(filesExts) {
    93  			continue
    94  		}
    95  
    96  		name := filepath.Base(file.Name)
    97  		ok2 := t.Run(name, func(t2 *testing.T) {
    98  			t2.Logf("run name: %v", name)
    99  			err := fn(t2, name, datas)
   100  			if err != nil {
   101  				t2.Fatal(ar.Error(err, fi))
   102  			}
   103  		})
   104  		if !ok2 {
   105  			break // stop on first failed test
   106  		}
   107  	}
   108  }
   109  
   110  //----------
   111  //----------
   112  //----------
   113  
   114  func countLines(b []byte) int {
   115  	return bytes.Count(b, []byte("\n"))
   116  }