diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..17380df --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +*.go -text diff=golang +*.txtar text eol=lf diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 6f0ae98..c14f9f8 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -6,7 +6,10 @@ name: CI branches: ["master"] jobs: check: - runs-on: ubuntu-latest + strategy: + matrix: + os: [ubuntu-latest, windows-latest] + runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v3 @@ -21,29 +24,29 @@ jobs: - name: Build run: go build -v ./... - name: Test - run: go test -v ./... - - name: Check examples - run: | - ./_examples/clean.sh - ./_examples/build-examples.sh - if $(git diff --quiet); then - echo "examples are clean" - else - echo "examples are dirty, rebuild it locally before commiting" - git diff | cat - exit 1 - fi - - name: Coverage report - run: | - go test -v -covermode=count -coverprofile=coverage.out -tags coverage ./... - go tool cover -func=coverage.out - - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v3 - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - - name: Vet - run: go vet - - name: golangci-lint - uses: golangci/golangci-lint-action@v3 - with: - version: v1.61.0 + run: go test -v "-test.v=true" ./... + # - name: Check examples + # run: | + # ./_examples/clean.sh + # ./_examples/build-examples.sh + # if $(git diff --quiet); then + # echo "examples are clean" + # else + # echo "examples are dirty, rebuild it locally before commiting" + # git diff | cat + # exit 1 + # fi + # - name: Coverage report + # run: | + # go test -v -covermode=count -coverprofile=coverage.out -tags coverage ./... + # go tool cover -func=coverage.out + # - name: Upload coverage reports to Codecov + # uses: codecov/codecov-action@v3 + # env: + # CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + # - name: Vet + # run: go vet + # - name: golangci-lint + # uses: golangci/golangci-lint-action@v3 + # with: + # version: v1.61.0 diff --git a/ast/file_test.go b/ast/file_test.go index aa66f6b..2c4adb6 100644 --- a/ast/file_test.go +++ b/ast/file_test.go @@ -2,12 +2,13 @@ package ast import ( "go/ast" + "path/filepath" "testing" ) func TestFileVisitor(t *testing.T) { fset, pkg, docs := loadTestFileSet(t) - fh, fv, file := testFileVisitor(fset, pkg, "testdata/onetype.go", docs) + fh, fv, file := testFileVisitor(t, fset, pkg, filepath.Join("testdata", "onetype.go"), docs) ast.Walk(fv, file) types := make([]*TypeSpec, 0) diff --git a/ast/parser_test.go b/ast/parser_test.go index b131948..e16bd93 100644 --- a/ast/parser_test.go +++ b/ast/parser_test.go @@ -3,7 +3,6 @@ package ast import ( "fmt" "os" - "path" "path/filepath" "strings" "testing" @@ -14,7 +13,7 @@ import ( ) func TestDataParser(t *testing.T) { - files, err := filepath.Glob("testdata/parser/*.txtar") + files, err := filepath.Glob(filepath.FromSlash("testdata/parser/*.txtar")) if err != nil { t.Fatalf("failed to list testdata files: %s", err) } @@ -27,17 +26,17 @@ func TestDataParser(t *testing.T) { file := file t.Run(filepath.Base(file), func(t *testing.T) { - t.Parallel() + // TODO: enable parallel tests after fixing #43 + // t.Parallel() + t.Logf("Parse txtar file: %q", file) ar, err := txtar.ParseFile(file) if err != nil { t.Fatalf("failed to parse txtar file: %s", err) } dir := t.TempDir() - if err := extractTxtar(ar, dir); err != nil { - t.Fatalf("failed to extract txtar: %s", err) - } + extractTxtar(t, ar, dir) tc := readTestCase(t, dir) testParser(t, dir, tc) @@ -305,25 +304,26 @@ func checkTypeRef(t *testing.T, prefix string, expect, res *FieldTypeRef) { } } -//--- +func extractTxtar(t *testing.T, ar *txtar.Archive, dir string) { + t.Helper() -func extractTxtar(ar *txtar.Archive, dir string) error { + t.Logf("Extracting txtar to %q", dir) for _, file := range ar.Files { name := filepath.Join(dir, file.Name) + t.Logf("Extracting %q to %q", file.Name, name) if err := os.MkdirAll(filepath.Dir(name), 0o777); err != nil { - return err + t.Fatalf("failed to create dir: %s", err) } if err := os.WriteFile(name, file.Data, 0o666); err != nil { - return err + t.Fatalf("failed to write file: %s", err) } } - return nil } func readTestCase(t *testing.T, dir string) parserTestCase { t.Helper() - testCaseFile, err := os.Open(path.Join(dir, "testcase.yaml")) + testCaseFile, err := os.Open(filepath.Join(dir, "testcase.yaml")) if err != nil { t.Fatalf("failed to open testcase file: %s", err) } diff --git a/ast/testhelper.go b/ast/testhelper.go index b9f0f37..ef3bd18 100644 --- a/ast/testhelper.go +++ b/ast/testhelper.go @@ -5,6 +5,7 @@ import ( "go/doc" "go/parser" "go/token" + "testing" ) type T interface { @@ -98,10 +99,16 @@ func (h *testFileHandler) onFile(f *FileSpec) interface { } //nolint:staticcheck -func testFileVisitor(fset *token.FileSet, pkg *ast.Package, fileName string, +func testFileVisitor(t *testing.T, + fset *token.FileSet, pkg *ast.Package, fileName string, docs *doc.Package, ) (*testFileHandler, *fileVisitor, *ast.File) { + t.Helper() + fileAst := pkg.Files[fileName] + if fileAst == nil { + t.Fatalf("file %q not found", fileName) + } fileTkn := fset.File(fileAst.Pos()) fileSpec := &FileSpec{ Name: fileTkn.Name(), diff --git a/ast/types_test.go b/ast/types_test.go index 07b303d..1634e59 100644 --- a/ast/types_test.go +++ b/ast/types_test.go @@ -35,7 +35,11 @@ func (h *typeHandler) onField(f *FieldSpec) FieldHandler { func TestTypesVisitor(t *testing.T) { fset, pkg, docs := loadTestFileSet(t) - file := pkg.Files["testdata/fields.go"] + file := getPkgFile(pkg, "testdata/fields.go") + if file == nil { + t.Fatal("package 'testdata' not found") + } + h := &fileHandler{} v := newFileVisitor(fset, file, docs, h) diff --git a/ast/utils.go b/ast/utils.go index df2cd63..f371979 100644 --- a/ast/utils.go +++ b/ast/utils.go @@ -140,3 +140,13 @@ func resolveTypeDocs(docs *doc.Package, t *ast.TypeSpec) string { } return docStr } + +func getPkgFile(pkg *ast.Package, name string) *ast.File { + for n, f := range pkg.Files { + // "./\\cfg\\config.go" to "./cfg/config.go" for windows + if strings.ReplaceAll(n, "/\\", "/") == name { + return f + } + } + return nil +} diff --git a/generator_test.go b/generator_test.go index 802d0be..cc2b01c 100644 --- a/generator_test.go +++ b/generator_test.go @@ -5,7 +5,6 @@ import ( "bytes" "io" "os" - "path" "path/filepath" "strings" "testing" @@ -53,7 +52,7 @@ func TestGenerator(t *testing.T) { var out bytes.Buffer runGenerator(t, gen, spec, dir, &out) - expectFile, err := os.Open(path.Join(dir, "expect.txt")) + expectFile, err := os.Open(filepath.Join(dir, "expect.txt")) if err != nil { t.Fatalf("failed to open expect.txt: %s", err) } diff --git a/i43/i43_test.go b/i43/i43_test.go new file mode 100644 index 0000000..48af508 --- /dev/null +++ b/i43/i43_test.go @@ -0,0 +1,42 @@ +package i43 + +import ( + "os" + "path/filepath" + "strings" + "testing" + + "golang.org/x/tools/txtar" +) + +func TestI43(t *testing.T) { + files, err := filepath.Glob(filepath.FromSlash("testdata/txtar/*.txtar")) + if err != nil { + t.Fatalf("failed to list testdata files: %s", err) + } + + t.Logf("Found %q txtars", strings.Join(files, ", ")) + + for _, f := range files { + t.Logf("parsing %q", f) + arch, err := txtar.ParseFile(f) + if err != nil { + t.Errorf("failed to parse txtar file %q: %s", f, err) + } + t.Logf("parsed %q txtar: %s", f, arch.Comment) + dir := t.TempDir() + for _, af := range arch.Files { + t.Logf("file %q: %s", af.Name, af.Data) + + name := filepath.Join(dir, af.Name) + t.Logf("Extracting %q to %q", af.Name, name) + if err := os.MkdirAll(filepath.Dir(name), 0o777); err != nil { + t.Fatalf("failed to create dir: %s", err) + } + if err := os.WriteFile(name, af.Data, 0o666); err != nil { + t.Fatalf("failed to write file: %s", err) + } + } + + } +} diff --git a/i43/testdata/txtar/data.txtar b/i43/testdata/txtar/data.txtar new file mode 100644 index 0000000..34cc48a --- /dev/null +++ b/i43/testdata/txtar/data.txtar @@ -0,0 +1,10 @@ +Test txtar + +-- one.txt -- +one + +-- two.txt -- +two + +-- subdir/three.txt -- +three