Merge pull request #2393 from vdemeester/gotestyourself-with-tools
Update gotestyourself to gotest.tools
This commit is contained in:
commit
0158a6fb34
@ -32,8 +32,8 @@ import (
|
|||||||
|
|
||||||
"github.com/containerd/fifo"
|
"github.com/containerd/fifo"
|
||||||
"github.com/google/go-cmp/cmp/cmpopts"
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||||||
"github.com/gotestyourself/gotestyourself/assert"
|
"gotest.tools/assert"
|
||||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
is "gotest.tools/assert/cmp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func assertHasPrefix(t *testing.T, s, prefix string) {
|
func assertHasPrefix(t *testing.T, s, prefix string) {
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/gotestyourself/gotestyourself/assert"
|
"gotest.tools/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestOpenFifos(t *testing.T) {
|
func TestOpenFifos(t *testing.T) {
|
||||||
|
@ -25,9 +25,9 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/gotestyourself/gotestyourself/assert"
|
|
||||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
|
"gotest.tools/assert"
|
||||||
|
is "gotest.tools/assert/cmp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type copySource struct {
|
type copySource struct {
|
||||||
|
@ -37,9 +37,9 @@ import (
|
|||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
"github.com/containerd/containerd/content/testsuite"
|
"github.com/containerd/containerd/content/testsuite"
|
||||||
"github.com/containerd/containerd/pkg/testutil"
|
"github.com/containerd/containerd/pkg/testutil"
|
||||||
"github.com/gotestyourself/gotestyourself/assert"
|
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
"gotest.tools/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
type memoryLabelStore struct {
|
type memoryLabelStore struct {
|
||||||
|
@ -31,10 +31,10 @@ import (
|
|||||||
|
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
"github.com/containerd/containerd/pkg/testutil"
|
"github.com/containerd/containerd/pkg/testutil"
|
||||||
"github.com/gotestyourself/gotestyourself/assert"
|
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"gotest.tools/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ContentSuite runs a test suite on the content store given a factory function.
|
// ContentSuite runs a test suite on the content store given a factory function.
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/containerd/gc"
|
"github.com/containerd/containerd/gc"
|
||||||
"github.com/gotestyourself/gotestyourself/assert"
|
"gotest.tools/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPauseThreshold(t *testing.T) {
|
func TestPauseThreshold(t *testing.T) {
|
||||||
|
@ -19,9 +19,9 @@ package oci
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/gotestyourself/gotestyourself/assert"
|
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
"gotest.tools/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNormalizeImageRef(t *testing.T) {
|
func TestNormalizeImageRef(t *testing.T) {
|
||||||
|
@ -20,7 +20,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/gotestyourself/gotestyourself/assert"
|
"gotest.tools/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLoggerContext(t *testing.T) {
|
func TestLoggerContext(t *testing.T) {
|
||||||
|
@ -36,7 +36,7 @@ import (
|
|||||||
|
|
||||||
"github.com/containerd/containerd/mount"
|
"github.com/containerd/containerd/mount"
|
||||||
"github.com/containerd/containerd/pkg/testutil"
|
"github.com/containerd/containerd/pkg/testutil"
|
||||||
"github.com/gotestyourself/gotestyourself/assert"
|
"gotest.tools/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func checkLookup(t *testing.T, fsType, mntPoint, dir string) {
|
func checkLookup(t *testing.T, fsType, mntPoint, dir string) {
|
||||||
|
@ -24,7 +24,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/containerd/containerd/mount"
|
"github.com/containerd/containerd/mount"
|
||||||
"github.com/gotestyourself/gotestyourself/assert"
|
"gotest.tools/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Unmount unmounts a given mountPoint and sets t.Error if it fails
|
// Unmount unmounts a given mountPoint and sets t.Error if it fails
|
||||||
|
@ -20,7 +20,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/containerd/containerd/reference"
|
"github.com/containerd/containerd/reference"
|
||||||
"github.com/gotestyourself/gotestyourself/assert"
|
"gotest.tools/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRepositoryScope(t *testing.T) {
|
func TestRepositoryScope(t *testing.T) {
|
||||||
|
@ -20,8 +20,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/gotestyourself/gotestyourself/assert"
|
"gotest.tools/assert"
|
||||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
is "gotest.tools/assert/cmp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNewErrorsWithSamePathForRootAndState(t *testing.T) {
|
func TestNewErrorsWithSamePathForRootAndState(t *testing.T) {
|
||||||
|
@ -27,9 +27,9 @@ import (
|
|||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/snapshots"
|
"github.com/containerd/containerd/snapshots"
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
"github.com/gotestyourself/gotestyourself/assert"
|
|
||||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"gotest.tools/assert"
|
||||||
|
is "gotest.tools/assert/cmp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type testFunc func(context.Context, *testing.T, *MetaStore)
|
type testFunc func(context.Context, *testing.T, *MetaStore)
|
||||||
|
@ -32,8 +32,8 @@ import (
|
|||||||
"github.com/containerd/containerd/pkg/testutil"
|
"github.com/containerd/containerd/pkg/testutil"
|
||||||
"github.com/containerd/containerd/snapshots"
|
"github.com/containerd/containerd/snapshots"
|
||||||
"github.com/containerd/continuity/fs/fstest"
|
"github.com/containerd/continuity/fs/fstest"
|
||||||
"github.com/gotestyourself/gotestyourself/assert"
|
"gotest.tools/assert"
|
||||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
is "gotest.tools/assert/cmp"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SnapshotterSuite runs a test suite on the snapshotter given a factory function.
|
// SnapshotterSuite runs a test suite on the snapshotter given a factory function.
|
||||||
|
@ -29,8 +29,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gotestyourself/gotestyourself/assert"
|
"gotest.tools/assert"
|
||||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
is "gotest.tools/assert/cmp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSetPositiveOomScoreAdjustment(t *testing.T) {
|
func TestSetPositiveOomScoreAdjustment(t *testing.T) {
|
||||||
|
@ -22,7 +22,6 @@ github.com/golang/protobuf v1.1.0
|
|||||||
github.com/opencontainers/runtime-spec v1.0.1
|
github.com/opencontainers/runtime-spec v1.0.1
|
||||||
github.com/opencontainers/runc 69663f0bd4b60df09991c08812a60108003fa340
|
github.com/opencontainers/runc 69663f0bd4b60df09991c08812a60108003fa340
|
||||||
github.com/sirupsen/logrus v1.0.0
|
github.com/sirupsen/logrus v1.0.0
|
||||||
github.com/pmezard/go-difflib v1.0.0
|
|
||||||
github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c
|
github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c
|
||||||
golang.org/x/net b3756b4b77d7b13260a0a2ec658753cf48922eac
|
golang.org/x/net b3756b4b77d7b13260a0a2ec658753cf48922eac
|
||||||
google.golang.org/grpc v1.12.0
|
google.golang.org/grpc v1.12.0
|
||||||
@ -40,7 +39,7 @@ google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
|
|||||||
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
|
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
|
||||||
github.com/stevvooe/ttrpc d4528379866b0ce7e9d71f3eb96f0582fc374577
|
github.com/stevvooe/ttrpc d4528379866b0ce7e9d71f3eb96f0582fc374577
|
||||||
github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16
|
github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16
|
||||||
github.com/gotestyourself/gotestyourself 44dbf532bbf5767611f6f2a61bded572e337010a
|
gotest.tools v2.1.0
|
||||||
github.com/google/go-cmp v0.1.0
|
github.com/google/go-cmp v0.1.0
|
||||||
|
|
||||||
github.com/containerd/cri 8bcb9a95394e8d7845da1d6a994d3ac2a86d22f0
|
github.com/containerd/cri 8bcb9a95394e8d7845da1d6a994d3ac2a86d22f0
|
||||||
|
33
vendor/github.com/gotestyourself/gotestyourself/README.md
generated
vendored
33
vendor/github.com/gotestyourself/gotestyourself/README.md
generated
vendored
@ -1,33 +0,0 @@
|
|||||||
# Go Test Yourself
|
|
||||||
|
|
||||||
A collection of packages compatible with `go test` to support common testing
|
|
||||||
patterns.
|
|
||||||
|
|
||||||
[](https://godoc.org/github.com/gotestyourself/gotestyourself)
|
|
||||||
[](https://circleci.com/gh/gotestyourself/gotestyourself/tree/master)
|
|
||||||
[](https://goreportcard.com/report/github.com/gotestyourself/gotestyourself)
|
|
||||||
|
|
||||||
|
|
||||||
## Packages
|
|
||||||
|
|
||||||
* [assert](http://godoc.org/github.com/gotestyourself/gotestyourself/assert) -
|
|
||||||
compare values and fail the test when the comparison fails
|
|
||||||
* [env](http://godoc.org/github.com/gotestyourself/gotestyourself/env) -
|
|
||||||
test code that uses environment variables
|
|
||||||
* [fs](http://godoc.org/github.com/gotestyourself/gotestyourself/fs) -
|
|
||||||
create test files and directories
|
|
||||||
* [golden](http://godoc.org/github.com/gotestyourself/gotestyourself/golden) -
|
|
||||||
compare large multi-line strings
|
|
||||||
* [icmd](http://godoc.org/github.com/gotestyourself/gotestyourself/icmd) -
|
|
||||||
execute binaries and test the output
|
|
||||||
* [poll](http://godoc.org/github.com/gotestyourself/gotestyourself/poll) -
|
|
||||||
test asynchronous code by polling until a desired state is reached
|
|
||||||
* [skip](http://godoc.org/github.com/gotestyourself/gotestyourself/skip) -
|
|
||||||
skip tests based on conditions
|
|
||||||
* [testsum](http://godoc.org/github.com/gotestyourself/gotestyourself/testsum) -
|
|
||||||
a program to summarize `go test` output and test failures
|
|
||||||
|
|
||||||
## Related
|
|
||||||
|
|
||||||
* [maxbrunsfeld/counterfeiter](https://github.com/maxbrunsfeld/counterfeiter) - generate fakes for interfaces
|
|
||||||
* [jonboulle/clockwork](https://github.com/jonboulle/clockwork) - a fake clock for testing code that uses `time`
|
|
50
vendor/github.com/pmezard/go-difflib/README.md
generated
vendored
50
vendor/github.com/pmezard/go-difflib/README.md
generated
vendored
@ -1,50 +0,0 @@
|
|||||||
go-difflib
|
|
||||||
==========
|
|
||||||
|
|
||||||
[](https://travis-ci.org/pmezard/go-difflib)
|
|
||||||
[](https://godoc.org/github.com/pmezard/go-difflib/difflib)
|
|
||||||
|
|
||||||
Go-difflib is a partial port of python 3 difflib package. Its main goal
|
|
||||||
was to make unified and context diff available in pure Go, mostly for
|
|
||||||
testing purposes.
|
|
||||||
|
|
||||||
The following class and functions (and related tests) have be ported:
|
|
||||||
|
|
||||||
* `SequenceMatcher`
|
|
||||||
* `unified_diff()`
|
|
||||||
* `context_diff()`
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ go get github.com/pmezard/go-difflib/difflib
|
|
||||||
```
|
|
||||||
|
|
||||||
### Quick Start
|
|
||||||
|
|
||||||
Diffs are configured with Unified (or ContextDiff) structures, and can
|
|
||||||
be output to an io.Writer or returned as a string.
|
|
||||||
|
|
||||||
```Go
|
|
||||||
diff := UnifiedDiff{
|
|
||||||
A: difflib.SplitLines("foo\nbar\n"),
|
|
||||||
B: difflib.SplitLines("foo\nbaz\n"),
|
|
||||||
FromFile: "Original",
|
|
||||||
ToFile: "Current",
|
|
||||||
Context: 3,
|
|
||||||
}
|
|
||||||
text, _ := GetUnifiedDiffString(diff)
|
|
||||||
fmt.Printf(text)
|
|
||||||
```
|
|
||||||
|
|
||||||
would output:
|
|
||||||
|
|
||||||
```
|
|
||||||
--- Original
|
|
||||||
+++ Current
|
|
||||||
@@ -1,3 +1,3 @@
|
|
||||||
foo
|
|
||||||
-bar
|
|
||||||
+baz
|
|
||||||
```
|
|
||||||
|
|
31
vendor/gotest.tools/README.md
vendored
Normal file
31
vendor/gotest.tools/README.md
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# gotest.tools
|
||||||
|
|
||||||
|
A collection of packages to augment `testing` and support common patterns.
|
||||||
|
|
||||||
|
[](https://godoc.org/gotest.tools)
|
||||||
|
[](https://circleci.com/gh/gotestyourself/gotestyourself/tree/master)
|
||||||
|
[](https://goreportcard.com/report/gotest.tools)
|
||||||
|
|
||||||
|
|
||||||
|
## Packages
|
||||||
|
|
||||||
|
* [assert](http://godoc.org/gotest.tools/assert) -
|
||||||
|
compare values and fail the test when a comparison fails
|
||||||
|
* [env](http://godoc.org/gotest.tools/env) -
|
||||||
|
test code which uses environment variables
|
||||||
|
* [fs](http://godoc.org/gotest.tools/fs) -
|
||||||
|
create temporary files and compare a filesystem tree to an expected value
|
||||||
|
* [golden](http://godoc.org/gotest.tools/golden) -
|
||||||
|
compare large multi-line strings against values frozen in golden files
|
||||||
|
* [icmd](http://godoc.org/gotest.tools/icmd) -
|
||||||
|
execute binaries and test the output
|
||||||
|
* [poll](http://godoc.org/gotest.tools/poll) -
|
||||||
|
test asynchronous code by polling until a desired state is reached
|
||||||
|
* [skip](http://godoc.org/gotest.tools/skip) -
|
||||||
|
skip a test and print the source code of the condition used to skip the test
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
* [gotest.tools/gotestsum](https://github.com/gotestyourself/gotestsum) - go test runner with custom output
|
||||||
|
* [maxbrunsfeld/counterfeiter](https://github.com/maxbrunsfeld/counterfeiter) - generate fakes for interfaces
|
||||||
|
* [jonboulle/clockwork](https://github.com/jonboulle/clockwork) - a fake clock for testing code that uses `time`
|
@ -8,7 +8,7 @@ comparison fails. The one difference is that Assert() will end the test executio
|
|||||||
immediately (using t.FailNow()) whereas Check() will fail the test (using t.Fail()),
|
immediately (using t.FailNow()) whereas Check() will fail the test (using t.Fail()),
|
||||||
return the value of the comparison, then proceed with the rest of the test case.
|
return the value of the comparison, then proceed with the rest of the test case.
|
||||||
|
|
||||||
Example Usage
|
Example usage
|
||||||
|
|
||||||
The example below shows assert used with some common types.
|
The example below shows assert used with some common types.
|
||||||
|
|
||||||
@ -16,8 +16,8 @@ The example below shows assert used with some common types.
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/gotestyourself/gotestyourself/assert"
|
"gotest.tools/assert"
|
||||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
is "gotest.tools/assert/cmp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEverything(t *testing.T) {
|
func TestEverything(t *testing.T) {
|
||||||
@ -32,15 +32,15 @@ The example below shows assert used with some common types.
|
|||||||
|
|
||||||
// errors
|
// errors
|
||||||
assert.NilError(t, closer.Close())
|
assert.NilError(t, closer.Close())
|
||||||
assert.Assert(t, is.Error(err, "the exact error message"))
|
assert.Error(t, err, "the exact error message")
|
||||||
assert.Assert(t, is.ErrorContains(err, "includes this"))
|
assert.ErrorContains(t, err, "includes this")
|
||||||
assert.Assert(t, os.IsNotExist(err), "got %+v", err)
|
assert.ErrorType(t, err, os.IsNotExist)
|
||||||
|
|
||||||
// complex types
|
// complex types
|
||||||
|
assert.DeepEqual(t, result, myStruct{Name: "title"})
|
||||||
assert.Assert(t, is.Len(items, 3))
|
assert.Assert(t, is.Len(items, 3))
|
||||||
assert.Assert(t, len(sequence) != 0) // NotEmpty
|
assert.Assert(t, len(sequence) != 0) // NotEmpty
|
||||||
assert.Assert(t, is.Contains(mapping, "key"))
|
assert.Assert(t, is.Contains(mapping, "key"))
|
||||||
assert.Assert(t, is.DeepEqual(result, myStruct{Name: "title"}))
|
|
||||||
|
|
||||||
// pointers and interface
|
// pointers and interface
|
||||||
assert.Assert(t, is.Nil(ref))
|
assert.Assert(t, is.Nil(ref))
|
||||||
@ -49,31 +49,30 @@ The example below shows assert used with some common types.
|
|||||||
|
|
||||||
Comparisons
|
Comparisons
|
||||||
|
|
||||||
https://godoc.org/github.com/gotestyourself/gotestyourself/assert/cmp provides
|
Package https://godoc.org/gotest.tools/assert/cmp provides
|
||||||
many common comparisons. Additional comparisons can be written to compare
|
many common comparisons. Additional comparisons can be written to compare
|
||||||
values in other ways.
|
values in other ways. See the example Assert (CustomComparison).
|
||||||
|
|
||||||
Below is an example of a custom comparison using a regex pattern:
|
Automated migration from testify
|
||||||
|
|
||||||
|
gty-migrate-from-testify is a binary which can update source code which uses
|
||||||
|
testify assertions to use the assertions provided by this package.
|
||||||
|
|
||||||
|
See http://bit.do/cmd-gty-migrate-from-testify.
|
||||||
|
|
||||||
func RegexP(value string, pattern string) func() (bool, string) {
|
|
||||||
return func() (bool, string) {
|
|
||||||
re := regexp.MustCompile(pattern)
|
|
||||||
msg := fmt.Sprintf("%q did not match pattern %q", value, pattern)
|
|
||||||
return re.MatchString(value), msg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package assert
|
package assert // import "gotest.tools/assert"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/token"
|
"go/token"
|
||||||
|
|
||||||
"github.com/gotestyourself/gotestyourself/assert/cmp"
|
gocmp "github.com/google/go-cmp/cmp"
|
||||||
"github.com/gotestyourself/gotestyourself/internal/format"
|
"gotest.tools/assert/cmp"
|
||||||
"github.com/gotestyourself/gotestyourself/internal/source"
|
"gotest.tools/internal/format"
|
||||||
|
"gotest.tools/internal/source"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BoolOrComparison can be a bool, or cmp.Comparison. See Assert() for usage.
|
// BoolOrComparison can be a bool, or cmp.Comparison. See Assert() for usage.
|
||||||
@ -96,7 +95,7 @@ const failureMessage = "assertion failed: "
|
|||||||
func assert(
|
func assert(
|
||||||
t TestingT,
|
t TestingT,
|
||||||
failer func(),
|
failer func(),
|
||||||
argsFilter astExprListFilter,
|
argSelector argSelector,
|
||||||
comparison BoolOrComparison,
|
comparison BoolOrComparison,
|
||||||
msgAndArgs ...interface{},
|
msgAndArgs ...interface{},
|
||||||
) bool {
|
) bool {
|
||||||
@ -123,10 +122,10 @@ func assert(
|
|||||||
t.Log(format.WithCustomMessage(failureMessage+msg+check.Error(), msgAndArgs...))
|
t.Log(format.WithCustomMessage(failureMessage+msg+check.Error(), msgAndArgs...))
|
||||||
|
|
||||||
case cmp.Comparison:
|
case cmp.Comparison:
|
||||||
success = runComparison(t, argsFilter, check, msgAndArgs...)
|
success = runComparison(t, argSelector, check, msgAndArgs...)
|
||||||
|
|
||||||
case func() cmp.Result:
|
case func() cmp.Result:
|
||||||
success = runComparison(t, argsFilter, check, msgAndArgs...)
|
success = runComparison(t, argSelector, check, msgAndArgs...)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
t.Log(fmt.Sprintf("invalid Comparison: %v (%T)", check, check))
|
t.Log(fmt.Sprintf("invalid Comparison: %v (%T)", check, check))
|
||||||
@ -155,6 +154,9 @@ func runCompareFunc(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func logFailureFromBool(t TestingT, msgAndArgs ...interface{}) {
|
func logFailureFromBool(t TestingT, msgAndArgs ...interface{}) {
|
||||||
|
if ht, ok := t.(helperT); ok {
|
||||||
|
ht.Helper()
|
||||||
|
}
|
||||||
const stackIndex = 3 // Assert()/Check(), assert(), formatFailureFromBool()
|
const stackIndex = 3 // Assert()/Check(), assert(), formatFailureFromBool()
|
||||||
const comparisonArgPos = 1
|
const comparisonArgPos = 1
|
||||||
args, err := source.CallExprArgs(stackIndex)
|
args, err := source.CallExprArgs(stackIndex)
|
||||||
@ -215,7 +217,7 @@ func Assert(t TestingT, comparison BoolOrComparison, msgAndArgs ...interface{})
|
|||||||
if ht, ok := t.(helperT); ok {
|
if ht, ok := t.(helperT); ok {
|
||||||
ht.Helper()
|
ht.Helper()
|
||||||
}
|
}
|
||||||
assert(t, t.FailNow, filterExprArgsFromComparison, comparison, msgAndArgs...)
|
assert(t, t.FailNow, argsFromComparisonCall, comparison, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check performs a comparison. If the comparison fails the test is marked as
|
// Check performs a comparison. If the comparison fails the test is marked as
|
||||||
@ -227,7 +229,7 @@ func Check(t TestingT, comparison BoolOrComparison, msgAndArgs ...interface{}) b
|
|||||||
if ht, ok := t.(helperT); ok {
|
if ht, ok := t.(helperT); ok {
|
||||||
ht.Helper()
|
ht.Helper()
|
||||||
}
|
}
|
||||||
return assert(t, t.Fail, filterExprArgsFromComparison, comparison, msgAndArgs...)
|
return assert(t, t.Fail, argsFromComparisonCall, comparison, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NilError fails the test immediately if err is not nil.
|
// NilError fails the test immediately if err is not nil.
|
||||||
@ -236,14 +238,74 @@ func NilError(t TestingT, err error, msgAndArgs ...interface{}) {
|
|||||||
if ht, ok := t.(helperT); ok {
|
if ht, ok := t.(helperT); ok {
|
||||||
ht.Helper()
|
ht.Helper()
|
||||||
}
|
}
|
||||||
assert(t, t.FailNow, filterExprExcludeFirst, err, msgAndArgs...)
|
assert(t, t.FailNow, argsAfterT, err, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equal uses the == operator to assert two values are equal and fails the test
|
// Equal uses the == operator to assert two values are equal and fails the test
|
||||||
// if they are not equal. This is equivalent to Assert(t, cmp.Equal(x, y)).
|
// if they are not equal.
|
||||||
|
//
|
||||||
|
// If the comparison fails Equal will use the variable names for x and y as part
|
||||||
|
// of the failure message to identify the actual and expected values.
|
||||||
|
//
|
||||||
|
// If either x or y are a multi-line string the failure message will include a
|
||||||
|
// unified diff of the two values. If the values only differ by whitespace
|
||||||
|
// the unified diff will be augmented by replacing whitespace characters with
|
||||||
|
// visible characters to identify the whitespace difference.
|
||||||
|
//
|
||||||
|
// This is equivalent to Assert(t, cmp.Equal(x, y)).
|
||||||
func Equal(t TestingT, x, y interface{}, msgAndArgs ...interface{}) {
|
func Equal(t TestingT, x, y interface{}, msgAndArgs ...interface{}) {
|
||||||
if ht, ok := t.(helperT); ok {
|
if ht, ok := t.(helperT); ok {
|
||||||
ht.Helper()
|
ht.Helper()
|
||||||
}
|
}
|
||||||
assert(t, t.FailNow, filterExprExcludeFirst, cmp.Equal(x, y), msgAndArgs...)
|
assert(t, t.FailNow, argsAfterT, cmp.Equal(x, y), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepEqual uses google/go-cmp (http://bit.do/go-cmp) to assert two values are
|
||||||
|
// equal and fails the test if they are not equal.
|
||||||
|
//
|
||||||
|
// Package https://godoc.org/gotest.tools/assert/opt provides some additional
|
||||||
|
// commonly used Options.
|
||||||
|
//
|
||||||
|
// This is equivalent to Assert(t, cmp.DeepEqual(x, y)).
|
||||||
|
func DeepEqual(t TestingT, x, y interface{}, opts ...gocmp.Option) {
|
||||||
|
if ht, ok := t.(helperT); ok {
|
||||||
|
ht.Helper()
|
||||||
|
}
|
||||||
|
assert(t, t.FailNow, argsAfterT, cmp.DeepEqual(x, y, opts...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error fails the test if err is nil, or the error message is not the expected
|
||||||
|
// message.
|
||||||
|
// Equivalent to Assert(t, cmp.Error(err, message)).
|
||||||
|
func Error(t TestingT, err error, message string, msgAndArgs ...interface{}) {
|
||||||
|
if ht, ok := t.(helperT); ok {
|
||||||
|
ht.Helper()
|
||||||
|
}
|
||||||
|
assert(t, t.FailNow, argsAfterT, cmp.Error(err, message), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorContains fails the test if err is nil, or the error message does not
|
||||||
|
// contain the expected substring.
|
||||||
|
// Equivalent to Assert(t, cmp.ErrorContains(err, substring)).
|
||||||
|
func ErrorContains(t TestingT, err error, substring string, msgAndArgs ...interface{}) {
|
||||||
|
if ht, ok := t.(helperT); ok {
|
||||||
|
ht.Helper()
|
||||||
|
}
|
||||||
|
assert(t, t.FailNow, argsAfterT, cmp.ErrorContains(err, substring), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorType fails the test if err is nil, or err is not the expected type.
|
||||||
|
//
|
||||||
|
// Expected can be one of:
|
||||||
|
// a func(error) bool which returns true if the error is the expected type,
|
||||||
|
// an instance of (or a pointer to) a struct of the expected type,
|
||||||
|
// a pointer to an interface the error is expected to implement,
|
||||||
|
// a reflect.Type of the expected struct or interface.
|
||||||
|
//
|
||||||
|
// Equivalent to Assert(t, cmp.ErrorType(err, expected)).
|
||||||
|
func ErrorType(t TestingT, err error, expected interface{}, msgAndArgs ...interface{}) {
|
||||||
|
if ht, ok := t.(helperT); ok {
|
||||||
|
ht.Helper()
|
||||||
|
}
|
||||||
|
assert(t, t.FailNow, argsAfterT, cmp.ErrorType(err, expected), msgAndArgs...)
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*Package cmp provides Comparisons for Assert and Check*/
|
/*Package cmp provides Comparisons for Assert and Check*/
|
||||||
package cmp
|
package cmp // import "gotest.tools/assert/cmp"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -7,7 +7,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
"github.com/pmezard/go-difflib/difflib"
|
"gotest.tools/internal/format"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Comparison is a function which compares values and returns ResultSuccess if
|
// Comparison is a function which compares values and returns ResultSuccess if
|
||||||
@ -15,10 +15,12 @@ import (
|
|||||||
// Result will contain a message about why it failed.
|
// Result will contain a message about why it failed.
|
||||||
type Comparison func() Result
|
type Comparison func() Result
|
||||||
|
|
||||||
// DeepEqual compares two values using https://godoc.org/github.com/google/go-cmp/cmp
|
// DeepEqual compares two values using google/go-cmp (http://bit.do/go-cmp)
|
||||||
// and succeeds if the values are equal.
|
// and succeeds if the values are equal.
|
||||||
//
|
//
|
||||||
// The comparison can be customized using comparison Options.
|
// The comparison can be customized using comparison Options.
|
||||||
|
// Package https://godoc.org/gotest.tools/assert/opt provides some additional
|
||||||
|
// commonly used Options.
|
||||||
func DeepEqual(x, y interface{}, opts ...cmp.Option) Comparison {
|
func DeepEqual(x, y interface{}, opts ...cmp.Option) Comparison {
|
||||||
return func() (result Result) {
|
return func() (result Result) {
|
||||||
defer func() {
|
defer func() {
|
||||||
@ -27,7 +29,10 @@ func DeepEqual(x, y interface{}, opts ...cmp.Option) Comparison {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
diff := cmp.Diff(x, y, opts...)
|
diff := cmp.Diff(x, y, opts...)
|
||||||
return toResult(diff == "", "\n"+diff)
|
if diff == "" {
|
||||||
|
return ResultSuccess
|
||||||
|
}
|
||||||
|
return multiLineDiffResult(diff)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,14 +58,15 @@ func toResult(success bool, msg string) Result {
|
|||||||
return ResultFailure(msg)
|
return ResultFailure(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equal succeeds if x == y.
|
// Equal succeeds if x == y. See assert.Equal for full documentation.
|
||||||
func Equal(x, y interface{}) Comparison {
|
func Equal(x, y interface{}) Comparison {
|
||||||
return func() Result {
|
return func() Result {
|
||||||
switch {
|
switch {
|
||||||
case x == y:
|
case x == y:
|
||||||
return ResultSuccess
|
return ResultSuccess
|
||||||
case isMultiLineStringCompare(x, y):
|
case isMultiLineStringCompare(x, y):
|
||||||
return multiLineStringDiffResult(x.(string), y.(string))
|
diff := format.UnifiedDiff(format.DiffConfig{A: x.(string), B: y.(string)})
|
||||||
|
return multiLineDiffResult(diff)
|
||||||
}
|
}
|
||||||
return ResultFailureTemplate(`
|
return ResultFailureTemplate(`
|
||||||
{{- .Data.x}} (
|
{{- .Data.x}} (
|
||||||
@ -86,15 +92,7 @@ func isMultiLineStringCompare(x, y interface{}) bool {
|
|||||||
return strings.Contains(strX, "\n") || strings.Contains(strY, "\n")
|
return strings.Contains(strX, "\n") || strings.Contains(strY, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func multiLineStringDiffResult(x, y string) Result {
|
func multiLineDiffResult(diff string) Result {
|
||||||
diff, err := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
|
|
||||||
A: difflib.SplitLines(x),
|
|
||||||
B: difflib.SplitLines(y),
|
|
||||||
Context: 3,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return ResultFailure(fmt.Sprintf("failed to diff: %s", err))
|
|
||||||
}
|
|
||||||
return ResultFailureTemplate(`
|
return ResultFailureTemplate(`
|
||||||
--- {{ with callArg 0 }}{{ formatNode . }}{{else}}←{{end}}
|
--- {{ with callArg 0 }}{{ formatNode . }}{{else}}←{{end}}
|
||||||
+++ {{ with callArg 1 }}{{ formatNode . }}{{else}}→{{end}}
|
+++ {{ with callArg 1 }}{{ formatNode . }}{{else}}→{{end}}
|
||||||
@ -237,3 +235,78 @@ func isNil(obj interface{}, msgFunc func(reflect.Value) string) Comparison {
|
|||||||
return ResultFailure(fmt.Sprintf("%v (type %s) can not be nil", value, value.Type()))
|
return ResultFailure(fmt.Sprintf("%v (type %s) can not be nil", value, value.Type()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ErrorType succeeds if err is not nil and is of the expected type.
|
||||||
|
//
|
||||||
|
// Expected can be one of:
|
||||||
|
// a func(error) bool which returns true if the error is the expected type,
|
||||||
|
// an instance of (or a pointer to) a struct of the expected type,
|
||||||
|
// a pointer to an interface the error is expected to implement,
|
||||||
|
// a reflect.Type of the expected struct or interface.
|
||||||
|
func ErrorType(err error, expected interface{}) Comparison {
|
||||||
|
return func() Result {
|
||||||
|
switch expectedType := expected.(type) {
|
||||||
|
case func(error) bool:
|
||||||
|
return cmpErrorTypeFunc(err, expectedType)
|
||||||
|
case reflect.Type:
|
||||||
|
if expectedType.Kind() == reflect.Interface {
|
||||||
|
return cmpErrorTypeImplementsType(err, expectedType)
|
||||||
|
}
|
||||||
|
return cmpErrorTypeEqualType(err, expectedType)
|
||||||
|
case nil:
|
||||||
|
return ResultFailure(fmt.Sprintf("invalid type for expected: nil"))
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedType := reflect.TypeOf(expected)
|
||||||
|
switch {
|
||||||
|
case expectedType.Kind() == reflect.Struct, isPtrToStruct(expectedType):
|
||||||
|
return cmpErrorTypeEqualType(err, expectedType)
|
||||||
|
case isPtrToInterface(expectedType):
|
||||||
|
return cmpErrorTypeImplementsType(err, expectedType.Elem())
|
||||||
|
}
|
||||||
|
return ResultFailure(fmt.Sprintf("invalid type for expected: %T", expected))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmpErrorTypeFunc(err error, f func(error) bool) Result {
|
||||||
|
if f(err) {
|
||||||
|
return ResultSuccess
|
||||||
|
}
|
||||||
|
actual := "nil"
|
||||||
|
if err != nil {
|
||||||
|
actual = fmt.Sprintf("%s (%T)", err, err)
|
||||||
|
}
|
||||||
|
return ResultFailureTemplate(`error is {{ .Data.actual }}
|
||||||
|
{{- with callArg 1 }}, not {{ formatNode . }}{{end -}}`,
|
||||||
|
map[string]interface{}{"actual": actual})
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmpErrorTypeEqualType(err error, expectedType reflect.Type) Result {
|
||||||
|
if err == nil {
|
||||||
|
return ResultFailure(fmt.Sprintf("error is nil, not %s", expectedType))
|
||||||
|
}
|
||||||
|
errValue := reflect.ValueOf(err)
|
||||||
|
if errValue.Type() == expectedType {
|
||||||
|
return ResultSuccess
|
||||||
|
}
|
||||||
|
return ResultFailure(fmt.Sprintf("error is %s (%T), not %s", err, err, expectedType))
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmpErrorTypeImplementsType(err error, expectedType reflect.Type) Result {
|
||||||
|
if err == nil {
|
||||||
|
return ResultFailure(fmt.Sprintf("error is nil, not %s", expectedType))
|
||||||
|
}
|
||||||
|
errValue := reflect.ValueOf(err)
|
||||||
|
if errValue.Type().Implements(expectedType) {
|
||||||
|
return ResultSuccess
|
||||||
|
}
|
||||||
|
return ResultFailure(fmt.Sprintf("error is %s (%T), not %s", err, err, expectedType))
|
||||||
|
}
|
||||||
|
|
||||||
|
func isPtrToInterface(typ reflect.Type) bool {
|
||||||
|
return typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Interface
|
||||||
|
}
|
||||||
|
|
||||||
|
func isPtrToStruct(typ reflect.Type) bool {
|
||||||
|
return typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct
|
||||||
|
}
|
@ -6,7 +6,7 @@ import (
|
|||||||
"go/ast"
|
"go/ast"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/gotestyourself/gotestyourself/internal/source"
|
"gotest.tools/internal/source"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Result of a Comparison.
|
// Result of a Comparison.
|
@ -4,14 +4,14 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
|
|
||||||
"github.com/gotestyourself/gotestyourself/assert/cmp"
|
"gotest.tools/assert/cmp"
|
||||||
"github.com/gotestyourself/gotestyourself/internal/format"
|
"gotest.tools/internal/format"
|
||||||
"github.com/gotestyourself/gotestyourself/internal/source"
|
"gotest.tools/internal/source"
|
||||||
)
|
)
|
||||||
|
|
||||||
func runComparison(
|
func runComparison(
|
||||||
t TestingT,
|
t TestingT,
|
||||||
exprFilter astExprListFilter,
|
argSelector argSelector,
|
||||||
f cmp.Comparison,
|
f cmp.Comparison,
|
||||||
msgAndArgs ...interface{},
|
msgAndArgs ...interface{},
|
||||||
) bool {
|
) bool {
|
||||||
@ -31,7 +31,7 @@ func runComparison(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Log(err.Error())
|
t.Log(err.Error())
|
||||||
}
|
}
|
||||||
message = typed.FailureMessage(filterPrintableExpr(exprFilter(args)))
|
message = typed.FailureMessage(filterPrintableExpr(argSelector(args)))
|
||||||
case resultBasic:
|
case resultBasic:
|
||||||
message = typed.FailureMessage()
|
message = typed.FailureMessage()
|
||||||
default:
|
default:
|
||||||
@ -50,9 +50,7 @@ type resultBasic interface {
|
|||||||
FailureMessage() string
|
FailureMessage() string
|
||||||
}
|
}
|
||||||
|
|
||||||
type astExprListFilter func([]ast.Expr) []ast.Expr
|
// filterPrintableExpr filters the ast.Expr slice to only include Expr that are
|
||||||
|
|
||||||
// filterPrintableExpr filters the ast.Expr slice to only include nodes that are
|
|
||||||
// easy to read when printed and contain relevant information to an assertion.
|
// easy to read when printed and contain relevant information to an assertion.
|
||||||
//
|
//
|
||||||
// Ident and SelectorExpr are included because they print nicely and the variable
|
// Ident and SelectorExpr are included because they print nicely and the variable
|
||||||
@ -63,24 +61,42 @@ type astExprListFilter func([]ast.Expr) []ast.Expr
|
|||||||
func filterPrintableExpr(args []ast.Expr) []ast.Expr {
|
func filterPrintableExpr(args []ast.Expr) []ast.Expr {
|
||||||
result := make([]ast.Expr, len(args))
|
result := make([]ast.Expr, len(args))
|
||||||
for i, arg := range args {
|
for i, arg := range args {
|
||||||
switch arg.(type) {
|
if isShortPrintableExpr(arg) {
|
||||||
case *ast.Ident, *ast.SelectorExpr, *ast.IndexExpr, *ast.SliceExpr:
|
|
||||||
result[i] = arg
|
result[i] = arg
|
||||||
default:
|
continue
|
||||||
result[i] = nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if starExpr, ok := arg.(*ast.StarExpr); ok {
|
||||||
|
result[i] = starExpr.X
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
result[i] = nil
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterExprExcludeFirst(args []ast.Expr) []ast.Expr {
|
func isShortPrintableExpr(expr ast.Expr) bool {
|
||||||
|
switch expr.(type) {
|
||||||
|
case *ast.Ident, *ast.SelectorExpr, *ast.IndexExpr, *ast.SliceExpr:
|
||||||
|
return true
|
||||||
|
case *ast.BinaryExpr, *ast.UnaryExpr:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
// CallExpr, ParenExpr, TypeAssertExpr, KeyValueExpr, StarExpr
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type argSelector func([]ast.Expr) []ast.Expr
|
||||||
|
|
||||||
|
func argsAfterT(args []ast.Expr) []ast.Expr {
|
||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return args[1:]
|
return args[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterExprArgsFromComparison(args []ast.Expr) []ast.Expr {
|
func argsFromComparisonCall(args []ast.Expr) []ast.Expr {
|
||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
@ -1,27 +1,10 @@
|
|||||||
// Package difflib is a partial port of Python difflib module.
|
/* Package difflib is a partial port of Python difflib module.
|
||||||
//
|
|
||||||
// It provides tools to compare sequences of strings and generate textual diffs.
|
|
||||||
//
|
|
||||||
// The following class and functions have been ported:
|
|
||||||
//
|
|
||||||
// - SequenceMatcher
|
|
||||||
//
|
|
||||||
// - unified_diff
|
|
||||||
//
|
|
||||||
// - context_diff
|
|
||||||
//
|
|
||||||
// Getting unified diffs was the main goal of the port. Keep in mind this code
|
|
||||||
// is mostly suitable to output text differences in a human friendly way, there
|
|
||||||
// are no guarantees generated diffs are consumable by patch(1).
|
|
||||||
package difflib
|
|
||||||
|
|
||||||
import (
|
Original source: https://github.com/pmezard/go-difflib
|
||||||
"bufio"
|
|
||||||
"bytes"
|
This file is trimmed to only the parts used by this repository.
|
||||||
"fmt"
|
*/
|
||||||
"io"
|
package difflib // import "gotest.tools/internal/difflib"
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func min(a, b int) int {
|
func min(a, b int) int {
|
||||||
if a < b {
|
if a < b {
|
||||||
@ -37,13 +20,6 @@ func max(a, b int) int {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func calculateRatio(matches, length int) float64 {
|
|
||||||
if length > 0 {
|
|
||||||
return 2.0 * float64(matches) / float64(length)
|
|
||||||
}
|
|
||||||
return 1.0
|
|
||||||
}
|
|
||||||
|
|
||||||
type Match struct {
|
type Match struct {
|
||||||
A int
|
A int
|
||||||
B int
|
B int
|
||||||
@ -103,14 +79,6 @@ func NewMatcher(a, b []string) *SequenceMatcher {
|
|||||||
return &m
|
return &m
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMatcherWithJunk(a, b []string, autoJunk bool,
|
|
||||||
isJunk func(string) bool) *SequenceMatcher {
|
|
||||||
|
|
||||||
m := SequenceMatcher{IsJunk: isJunk, autoJunk: autoJunk}
|
|
||||||
m.SetSeqs(a, b)
|
|
||||||
return &m
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set two sequences to be compared.
|
// Set two sequences to be compared.
|
||||||
func (m *SequenceMatcher) SetSeqs(a, b []string) {
|
func (m *SequenceMatcher) SetSeqs(a, b []string) {
|
||||||
m.SetSeq1(a)
|
m.SetSeq1(a)
|
||||||
@ -450,323 +418,3 @@ func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode {
|
|||||||
}
|
}
|
||||||
return groups
|
return groups
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return a measure of the sequences' similarity (float in [0,1]).
|
|
||||||
//
|
|
||||||
// Where T is the total number of elements in both sequences, and
|
|
||||||
// M is the number of matches, this is 2.0*M / T.
|
|
||||||
// Note that this is 1 if the sequences are identical, and 0 if
|
|
||||||
// they have nothing in common.
|
|
||||||
//
|
|
||||||
// .Ratio() is expensive to compute if you haven't already computed
|
|
||||||
// .GetMatchingBlocks() or .GetOpCodes(), in which case you may
|
|
||||||
// want to try .QuickRatio() or .RealQuickRation() first to get an
|
|
||||||
// upper bound.
|
|
||||||
func (m *SequenceMatcher) Ratio() float64 {
|
|
||||||
matches := 0
|
|
||||||
for _, m := range m.GetMatchingBlocks() {
|
|
||||||
matches += m.Size
|
|
||||||
}
|
|
||||||
return calculateRatio(matches, len(m.a)+len(m.b))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return an upper bound on ratio() relatively quickly.
|
|
||||||
//
|
|
||||||
// This isn't defined beyond that it is an upper bound on .Ratio(), and
|
|
||||||
// is faster to compute.
|
|
||||||
func (m *SequenceMatcher) QuickRatio() float64 {
|
|
||||||
// viewing a and b as multisets, set matches to the cardinality
|
|
||||||
// of their intersection; this counts the number of matches
|
|
||||||
// without regard to order, so is clearly an upper bound
|
|
||||||
if m.fullBCount == nil {
|
|
||||||
m.fullBCount = map[string]int{}
|
|
||||||
for _, s := range m.b {
|
|
||||||
m.fullBCount[s] = m.fullBCount[s] + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// avail[x] is the number of times x appears in 'b' less the
|
|
||||||
// number of times we've seen it in 'a' so far ... kinda
|
|
||||||
avail := map[string]int{}
|
|
||||||
matches := 0
|
|
||||||
for _, s := range m.a {
|
|
||||||
n, ok := avail[s]
|
|
||||||
if !ok {
|
|
||||||
n = m.fullBCount[s]
|
|
||||||
}
|
|
||||||
avail[s] = n - 1
|
|
||||||
if n > 0 {
|
|
||||||
matches += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return calculateRatio(matches, len(m.a)+len(m.b))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return an upper bound on ratio() very quickly.
|
|
||||||
//
|
|
||||||
// This isn't defined beyond that it is an upper bound on .Ratio(), and
|
|
||||||
// is faster to compute than either .Ratio() or .QuickRatio().
|
|
||||||
func (m *SequenceMatcher) RealQuickRatio() float64 {
|
|
||||||
la, lb := len(m.a), len(m.b)
|
|
||||||
return calculateRatio(min(la, lb), la+lb)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert range to the "ed" format
|
|
||||||
func formatRangeUnified(start, stop int) string {
|
|
||||||
// Per the diff spec at http://www.unix.org/single_unix_specification/
|
|
||||||
beginning := start + 1 // lines start numbering with one
|
|
||||||
length := stop - start
|
|
||||||
if length == 1 {
|
|
||||||
return fmt.Sprintf("%d", beginning)
|
|
||||||
}
|
|
||||||
if length == 0 {
|
|
||||||
beginning -= 1 // empty ranges begin at line just before the range
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%d,%d", beginning, length)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unified diff parameters
|
|
||||||
type UnifiedDiff struct {
|
|
||||||
A []string // First sequence lines
|
|
||||||
FromFile string // First file name
|
|
||||||
FromDate string // First file time
|
|
||||||
B []string // Second sequence lines
|
|
||||||
ToFile string // Second file name
|
|
||||||
ToDate string // Second file time
|
|
||||||
Eol string // Headers end of line, defaults to LF
|
|
||||||
Context int // Number of context lines
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare two sequences of lines; generate the delta as a unified diff.
|
|
||||||
//
|
|
||||||
// Unified diffs are a compact way of showing line changes and a few
|
|
||||||
// lines of context. The number of context lines is set by 'n' which
|
|
||||||
// defaults to three.
|
|
||||||
//
|
|
||||||
// By default, the diff control lines (those with ---, +++, or @@) are
|
|
||||||
// created with a trailing newline. This is helpful so that inputs
|
|
||||||
// created from file.readlines() result in diffs that are suitable for
|
|
||||||
// file.writelines() since both the inputs and outputs have trailing
|
|
||||||
// newlines.
|
|
||||||
//
|
|
||||||
// For inputs that do not have trailing newlines, set the lineterm
|
|
||||||
// argument to "" so that the output will be uniformly newline free.
|
|
||||||
//
|
|
||||||
// The unidiff format normally has a header for filenames and modification
|
|
||||||
// times. Any or all of these may be specified using strings for
|
|
||||||
// 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'.
|
|
||||||
// The modification times are normally expressed in the ISO 8601 format.
|
|
||||||
func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error {
|
|
||||||
buf := bufio.NewWriter(writer)
|
|
||||||
defer buf.Flush()
|
|
||||||
wf := func(format string, args ...interface{}) error {
|
|
||||||
_, err := buf.WriteString(fmt.Sprintf(format, args...))
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
ws := func(s string) error {
|
|
||||||
_, err := buf.WriteString(s)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(diff.Eol) == 0 {
|
|
||||||
diff.Eol = "\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
started := false
|
|
||||||
m := NewMatcher(diff.A, diff.B)
|
|
||||||
for _, g := range m.GetGroupedOpCodes(diff.Context) {
|
|
||||||
if !started {
|
|
||||||
started = true
|
|
||||||
fromDate := ""
|
|
||||||
if len(diff.FromDate) > 0 {
|
|
||||||
fromDate = "\t" + diff.FromDate
|
|
||||||
}
|
|
||||||
toDate := ""
|
|
||||||
if len(diff.ToDate) > 0 {
|
|
||||||
toDate = "\t" + diff.ToDate
|
|
||||||
}
|
|
||||||
if diff.FromFile != "" || diff.ToFile != "" {
|
|
||||||
err := wf("--- %s%s%s", diff.FromFile, fromDate, diff.Eol)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = wf("+++ %s%s%s", diff.ToFile, toDate, diff.Eol)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
first, last := g[0], g[len(g)-1]
|
|
||||||
range1 := formatRangeUnified(first.I1, last.I2)
|
|
||||||
range2 := formatRangeUnified(first.J1, last.J2)
|
|
||||||
if err := wf("@@ -%s +%s @@%s", range1, range2, diff.Eol); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, c := range g {
|
|
||||||
i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
|
|
||||||
if c.Tag == 'e' {
|
|
||||||
for _, line := range diff.A[i1:i2] {
|
|
||||||
if err := ws(" " + line); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if c.Tag == 'r' || c.Tag == 'd' {
|
|
||||||
for _, line := range diff.A[i1:i2] {
|
|
||||||
if err := ws("-" + line); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if c.Tag == 'r' || c.Tag == 'i' {
|
|
||||||
for _, line := range diff.B[j1:j2] {
|
|
||||||
if err := ws("+" + line); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Like WriteUnifiedDiff but returns the diff a string.
|
|
||||||
func GetUnifiedDiffString(diff UnifiedDiff) (string, error) {
|
|
||||||
w := &bytes.Buffer{}
|
|
||||||
err := WriteUnifiedDiff(w, diff)
|
|
||||||
return string(w.Bytes()), err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert range to the "ed" format.
|
|
||||||
func formatRangeContext(start, stop int) string {
|
|
||||||
// Per the diff spec at http://www.unix.org/single_unix_specification/
|
|
||||||
beginning := start + 1 // lines start numbering with one
|
|
||||||
length := stop - start
|
|
||||||
if length == 0 {
|
|
||||||
beginning -= 1 // empty ranges begin at line just before the range
|
|
||||||
}
|
|
||||||
if length <= 1 {
|
|
||||||
return fmt.Sprintf("%d", beginning)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%d,%d", beginning, beginning+length-1)
|
|
||||||
}
|
|
||||||
|
|
||||||
type ContextDiff UnifiedDiff
|
|
||||||
|
|
||||||
// Compare two sequences of lines; generate the delta as a context diff.
|
|
||||||
//
|
|
||||||
// Context diffs are a compact way of showing line changes and a few
|
|
||||||
// lines of context. The number of context lines is set by diff.Context
|
|
||||||
// which defaults to three.
|
|
||||||
//
|
|
||||||
// By default, the diff control lines (those with *** or ---) are
|
|
||||||
// created with a trailing newline.
|
|
||||||
//
|
|
||||||
// For inputs that do not have trailing newlines, set the diff.Eol
|
|
||||||
// argument to "" so that the output will be uniformly newline free.
|
|
||||||
//
|
|
||||||
// The context diff format normally has a header for filenames and
|
|
||||||
// modification times. Any or all of these may be specified using
|
|
||||||
// strings for diff.FromFile, diff.ToFile, diff.FromDate, diff.ToDate.
|
|
||||||
// The modification times are normally expressed in the ISO 8601 format.
|
|
||||||
// If not specified, the strings default to blanks.
|
|
||||||
func WriteContextDiff(writer io.Writer, diff ContextDiff) error {
|
|
||||||
buf := bufio.NewWriter(writer)
|
|
||||||
defer buf.Flush()
|
|
||||||
var diffErr error
|
|
||||||
wf := func(format string, args ...interface{}) {
|
|
||||||
_, err := buf.WriteString(fmt.Sprintf(format, args...))
|
|
||||||
if diffErr == nil && err != nil {
|
|
||||||
diffErr = err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ws := func(s string) {
|
|
||||||
_, err := buf.WriteString(s)
|
|
||||||
if diffErr == nil && err != nil {
|
|
||||||
diffErr = err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(diff.Eol) == 0 {
|
|
||||||
diff.Eol = "\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
prefix := map[byte]string{
|
|
||||||
'i': "+ ",
|
|
||||||
'd': "- ",
|
|
||||||
'r': "! ",
|
|
||||||
'e': " ",
|
|
||||||
}
|
|
||||||
|
|
||||||
started := false
|
|
||||||
m := NewMatcher(diff.A, diff.B)
|
|
||||||
for _, g := range m.GetGroupedOpCodes(diff.Context) {
|
|
||||||
if !started {
|
|
||||||
started = true
|
|
||||||
fromDate := ""
|
|
||||||
if len(diff.FromDate) > 0 {
|
|
||||||
fromDate = "\t" + diff.FromDate
|
|
||||||
}
|
|
||||||
toDate := ""
|
|
||||||
if len(diff.ToDate) > 0 {
|
|
||||||
toDate = "\t" + diff.ToDate
|
|
||||||
}
|
|
||||||
if diff.FromFile != "" || diff.ToFile != "" {
|
|
||||||
wf("*** %s%s%s", diff.FromFile, fromDate, diff.Eol)
|
|
||||||
wf("--- %s%s%s", diff.ToFile, toDate, diff.Eol)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
first, last := g[0], g[len(g)-1]
|
|
||||||
ws("***************" + diff.Eol)
|
|
||||||
|
|
||||||
range1 := formatRangeContext(first.I1, last.I2)
|
|
||||||
wf("*** %s ****%s", range1, diff.Eol)
|
|
||||||
for _, c := range g {
|
|
||||||
if c.Tag == 'r' || c.Tag == 'd' {
|
|
||||||
for _, cc := range g {
|
|
||||||
if cc.Tag == 'i' {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, line := range diff.A[cc.I1:cc.I2] {
|
|
||||||
ws(prefix[cc.Tag] + line)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
range2 := formatRangeContext(first.J1, last.J2)
|
|
||||||
wf("--- %s ----%s", range2, diff.Eol)
|
|
||||||
for _, c := range g {
|
|
||||||
if c.Tag == 'r' || c.Tag == 'i' {
|
|
||||||
for _, cc := range g {
|
|
||||||
if cc.Tag == 'd' {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, line := range diff.B[cc.J1:cc.J2] {
|
|
||||||
ws(prefix[cc.Tag] + line)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return diffErr
|
|
||||||
}
|
|
||||||
|
|
||||||
// Like WriteContextDiff but returns the diff a string.
|
|
||||||
func GetContextDiffString(diff ContextDiff) (string, error) {
|
|
||||||
w := &bytes.Buffer{}
|
|
||||||
err := WriteContextDiff(w, diff)
|
|
||||||
return string(w.Bytes()), err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Split a string on "\n" while preserving them. The output can be used
|
|
||||||
// as input for UnifiedDiff and ContextDiff structures.
|
|
||||||
func SplitLines(s string) []string {
|
|
||||||
lines := strings.SplitAfter(s, "\n")
|
|
||||||
lines[len(lines)-1] += "\n"
|
|
||||||
return lines
|
|
||||||
}
|
|
161
vendor/gotest.tools/internal/format/diff.go
vendored
Normal file
161
vendor/gotest.tools/internal/format/diff.go
vendored
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
package format
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
|
"gotest.tools/internal/difflib"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
contextLines = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
// DiffConfig for a unified diff
|
||||||
|
type DiffConfig struct {
|
||||||
|
A string
|
||||||
|
B string
|
||||||
|
From string
|
||||||
|
To string
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnifiedDiff is a modified version of difflib.WriteUnifiedDiff with better
|
||||||
|
// support for showing the whitespace differences.
|
||||||
|
func UnifiedDiff(conf DiffConfig) string {
|
||||||
|
a := strings.SplitAfter(conf.A, "\n")
|
||||||
|
b := strings.SplitAfter(conf.B, "\n")
|
||||||
|
groups := difflib.NewMatcher(a, b).GetGroupedOpCodes(contextLines)
|
||||||
|
if len(groups) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
writeFormat := func(format string, args ...interface{}) {
|
||||||
|
buf.WriteString(fmt.Sprintf(format, args...))
|
||||||
|
}
|
||||||
|
writeLine := func(prefix string, s string) {
|
||||||
|
buf.WriteString(prefix + s)
|
||||||
|
}
|
||||||
|
if hasWhitespaceDiffLines(groups, a, b) {
|
||||||
|
writeLine = visibleWhitespaceLine(writeLine)
|
||||||
|
}
|
||||||
|
formatHeader(writeFormat, conf)
|
||||||
|
for _, group := range groups {
|
||||||
|
formatRangeLine(writeFormat, group)
|
||||||
|
for _, opCode := range group {
|
||||||
|
in, out := a[opCode.I1:opCode.I2], b[opCode.J1:opCode.J2]
|
||||||
|
switch opCode.Tag {
|
||||||
|
case 'e':
|
||||||
|
formatLines(writeLine, " ", in)
|
||||||
|
case 'r':
|
||||||
|
formatLines(writeLine, "-", in)
|
||||||
|
formatLines(writeLine, "+", out)
|
||||||
|
case 'd':
|
||||||
|
formatLines(writeLine, "-", in)
|
||||||
|
case 'i':
|
||||||
|
formatLines(writeLine, "+", out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// hasWhitespaceDiffLines returns true if any diff groups is only different
|
||||||
|
// because of whitespace characters.
|
||||||
|
func hasWhitespaceDiffLines(groups [][]difflib.OpCode, a, b []string) bool {
|
||||||
|
for _, group := range groups {
|
||||||
|
in, out := new(bytes.Buffer), new(bytes.Buffer)
|
||||||
|
for _, opCode := range group {
|
||||||
|
if opCode.Tag == 'e' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, line := range a[opCode.I1:opCode.I2] {
|
||||||
|
in.WriteString(line)
|
||||||
|
}
|
||||||
|
for _, line := range b[opCode.J1:opCode.J2] {
|
||||||
|
out.WriteString(line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if removeWhitespace(in.String()) == removeWhitespace(out.String()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeWhitespace(s string) string {
|
||||||
|
var result []rune
|
||||||
|
for _, r := range s {
|
||||||
|
if !unicode.IsSpace(r) {
|
||||||
|
result = append(result, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func visibleWhitespaceLine(ws func(string, string)) func(string, string) {
|
||||||
|
mapToVisibleSpace := func(r rune) rune {
|
||||||
|
switch r {
|
||||||
|
case '\n':
|
||||||
|
case ' ':
|
||||||
|
return '·'
|
||||||
|
case '\t':
|
||||||
|
return '▷'
|
||||||
|
case '\v':
|
||||||
|
return '▽'
|
||||||
|
case '\r':
|
||||||
|
return '↵'
|
||||||
|
case '\f':
|
||||||
|
return '↓'
|
||||||
|
default:
|
||||||
|
if unicode.IsSpace(r) {
|
||||||
|
return '<27>'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
return func(prefix, s string) {
|
||||||
|
ws(prefix, strings.Map(mapToVisibleSpace, s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func formatHeader(wf func(string, ...interface{}), conf DiffConfig) {
|
||||||
|
if conf.From != "" || conf.To != "" {
|
||||||
|
wf("--- %s\n", conf.From)
|
||||||
|
wf("+++ %s\n", conf.To)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func formatRangeLine(wf func(string, ...interface{}), group []difflib.OpCode) {
|
||||||
|
first, last := group[0], group[len(group)-1]
|
||||||
|
range1 := formatRangeUnified(first.I1, last.I2)
|
||||||
|
range2 := formatRangeUnified(first.J1, last.J2)
|
||||||
|
wf("@@ -%s +%s @@\n", range1, range2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert range to the "ed" format
|
||||||
|
func formatRangeUnified(start, stop int) string {
|
||||||
|
// Per the diff spec at http://www.unix.org/single_unix_specification/
|
||||||
|
beginning := start + 1 // lines start numbering with one
|
||||||
|
length := stop - start
|
||||||
|
if length == 1 {
|
||||||
|
return fmt.Sprintf("%d", beginning)
|
||||||
|
}
|
||||||
|
if length == 0 {
|
||||||
|
beginning-- // empty ranges begin at line just before the range
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%d,%d", beginning, length)
|
||||||
|
}
|
||||||
|
|
||||||
|
func formatLines(writeLine func(string, string), prefix string, lines []string) {
|
||||||
|
for _, line := range lines {
|
||||||
|
writeLine(prefix, line)
|
||||||
|
}
|
||||||
|
// Add a newline if the last line is missing one so that the diff displays
|
||||||
|
// properly.
|
||||||
|
if !strings.HasSuffix(lines[len(lines)-1], "\n") {
|
||||||
|
writeLine("", "\n")
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package format
|
package format // import "gotest.tools/internal/format"
|
||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package source
|
package source // import "gotest.tools/internal/source"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@ -68,12 +68,14 @@ func (v *scanToLineVisitor) Visit(node ast.Node) ast.Visitor {
|
|||||||
// In golang 1.9 the line number changed from being the line where the statement
|
// In golang 1.9 the line number changed from being the line where the statement
|
||||||
// ended to the line where the statement began.
|
// ended to the line where the statement began.
|
||||||
func (v *scanToLineVisitor) nodePosition(node ast.Node) token.Position {
|
func (v *scanToLineVisitor) nodePosition(node ast.Node) token.Position {
|
||||||
if isGOVersionBefore19() {
|
if goVersionBefore19 {
|
||||||
return v.fileset.Position(node.End())
|
return v.fileset.Position(node.End())
|
||||||
}
|
}
|
||||||
return v.fileset.Position(node.Pos())
|
return v.fileset.Position(node.Pos())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var goVersionBefore19 = isGOVersionBefore19()
|
||||||
|
|
||||||
func isGOVersionBefore19() bool {
|
func isGOVersionBefore19() bool {
|
||||||
version := runtime.Version()
|
version := runtime.Version()
|
||||||
// not a release version
|
// not a release version
|
Loading…
Reference in New Issue
Block a user