Skip to content

Commit 362d2ae

Browse files
committed
Improve coverage in proteus
This improves coverage in all packages in proteus and extract common utils to go-parse-utils
1 parent 6cc0e36 commit 362d2ae

16 files changed

+297
-279
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,5 @@ _testmain.go
2222
*.exe
2323
*.test
2424
*.prof
25+
26+
coverage.txt

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ matrix:
99
- go: tip
1010

1111
install:
12-
- go get -t -v ./...
12+
- go get -t -u -v ./...
1313

1414
script:
1515
- make test

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ COVERAGE_MODE := atomic
44

55
test:
66
@echo "mode: $(COVERAGE_MODE)" > $(COVERAGE_REPORT); \
7-
for dir in `find . -name "*.go" | grep -o '.*/' | sort -u`; do \
7+
for dir in `find . -name "*.go" | grep -o '.*/' | sort -u | grep -v './fixtures/'`; do \
88
go test $$dir -coverprofile=$(COVERAGE_PROFILE) -covermode=$(COVERAGE_MODE); \
99
if [ $$? != 0 ]; then \
1010
exit 2; \

rpc/context.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,16 @@ func firstTypeName(tuple *types.Tuple) types.Object {
8080
return t.(*types.Named).Obj()
8181
}
8282

83+
func (c *context) pkgPath() string {
84+
if c.pkg != nil {
85+
return c.pkg.Path()
86+
}
87+
88+
return ""
89+
}
90+
8391
func (c *context) addImport(path string) {
84-
if path == c.pkg.Path() {
92+
if path == c.pkgPath() {
8593
return
8694
}
8795

rpc/context_test.go

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package rpc
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/src-d/proteus/protobuf"
8+
"github.com/stretchr/testify/assert"
9+
10+
"gopkg.in/src-d/go-parse-utils.v1"
11+
)
12+
13+
func TestContext_isNameDefined(t *testing.T) {
14+
pkg, err := parseutil.NewImporter().Import("github.com/src-d/proteus/fixtures")
15+
if err != nil {
16+
assert.Fail(t, fmt.Sprintf("could not import project fixtures: %v", err))
17+
}
18+
ctx := &context{pkg: pkg}
19+
20+
assert.True(t, ctx.isNameDefined("Foo"), "Generator is defined")
21+
assert.False(t, ctx.isNameDefined("supercalifragilisticexpialidocious"), "this pakage has something to say")
22+
}
23+
24+
func TestContext_findMessage(t *testing.T) {
25+
ctx := &context{
26+
proto: &protobuf.Package{
27+
Messages: []*protobuf.Message{
28+
&protobuf.Message{Name: "a"},
29+
},
30+
},
31+
}
32+
33+
var msg *protobuf.Message
34+
msg = ctx.findMessage("a")
35+
assert.NotNil(t, msg)
36+
37+
msg = ctx.findMessage("nothere")
38+
assert.Nil(t, msg)
39+
}
40+
41+
func TestContext_addImport(t *testing.T) {
42+
ctx := &context{}
43+
44+
assert.Equal(t, 0, len(ctx.imports))
45+
ctx.addImport("my-path")
46+
assert.Equal(t, 1, len(ctx.imports))
47+
48+
ctx.addImport("other-path")
49+
assert.Equal(t, 2, len(ctx.imports), "adds other element")
50+
51+
ctx.addImport("my-path")
52+
assert.Equal(t, 2, len(ctx.imports), "does not addd the same element twice")
53+
}

rpc/rpc.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import (
1111

1212
"github.com/src-d/proteus/protobuf"
1313
"github.com/src-d/proteus/report"
14-
"github.com/src-d/proteus/source"
14+
15+
"gopkg.in/src-d/go-parse-utils.v1"
1516
)
1617

1718
// Generator generates implementations of an RPC server for a package.
@@ -45,12 +46,12 @@ import (
4546
// The file will be written to the package path and it will be named
4647
// "server.proteus.go"
4748
type Generator struct {
48-
importer *source.Importer
49+
importer *parseutil.Importer
4950
}
5051

5152
// NewGenerator creates a new Generator.
5253
func NewGenerator() *Generator {
53-
return &Generator{source.NewImporter()}
54+
return &Generator{parseutil.NewImporter()}
5455
}
5556

5657
// Generate creates a new file in the package at the given path and implements

rpc/rpc_test.go

+24
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ const expectedFuncNotGenerated = `func (s *FooServer) DoFoo(ctx context.Context,
5353
return
5454
}`
5555

56+
const expectedFuncNotGeneratedAndNotNullable = `func (s *FooServer) DoFoo(ctx context.Context, in *Foo) (result *Bar, err error) {
57+
result = new(Bar)
58+
aux := DoFoo(in)
59+
result = &aux
60+
return
61+
}`
62+
5663
const expectedFuncGenerated = `func (s *FooServer) DoFoo(ctx context.Context, in *FooRequest) (result *FooResponse, err error) {
5764
result = new(FooResponse)
5865
result.Result1, result.Result2, result.Result3 = DoFoo(in.Arg1, in.Arg2, in.Arg3)
@@ -109,6 +116,16 @@ func (s *RPCSuite) TestDeclMethod() {
109116
},
110117
expectedFuncNotGenerated,
111118
},
119+
{
120+
"func output not generated and not nullable",
121+
&protobuf.RPC{
122+
Name: "DoFoo",
123+
Method: "DoFoo",
124+
Input: protobuf.NewNamed("", "Foo"),
125+
Output: notNullable(protobuf.NewNamed("", "Bar")),
126+
},
127+
expectedFuncNotGeneratedAndNotNullable,
128+
},
112129
{
113130
"func generated",
114131
&protobuf.RPC{
@@ -366,6 +383,13 @@ func (s *RPCSuite) fakePkg() *types.Package {
366383
return pkg
367384
}
368385

386+
func notNullable(t protobuf.Type) protobuf.Type {
387+
src := scanner.NewNamed("", "X")
388+
src.SetNullable(false)
389+
t.SetSource(src)
390+
return t
391+
}
392+
369393
func render(decl ast.Decl) (string, error) {
370394
var buf bytes.Buffer
371395
if err := printer.Fprint(&buf, token.NewFileSet(), decl); err != nil {

scanner/context.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
"go/token"
77
"strings"
88

9-
"github.com/src-d/proteus/source"
9+
"gopkg.in/src-d/go-parse-utils.v1"
1010
)
1111

1212
// context holds all the scanning context of a single package. Contains all
@@ -31,7 +31,7 @@ type context struct {
3131
}
3232

3333
func newContext(path string) (*context, error) {
34-
pkg, err := source.PackageAST(path)
34+
pkg, err := parseutil.PackageAST(path)
3535
if err != nil {
3636
return nil, err
3737
}

scanner/context_test.go

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package scanner
2+
3+
import (
4+
"os"
5+
"path/filepath"
6+
"testing"
7+
8+
"github.com/stretchr/testify/assert"
9+
)
10+
11+
var goSrc = filepath.Join(os.Getenv("GOPATH"), "src")
12+
var projectDir = filepath.Join(goSrc, "github.com/src-d/proteus")
13+
14+
func TestNewContext_error(t *testing.T) {
15+
createDirWithMultipleFiles("erroring")
16+
defer removeDir("erroring")
17+
_, err := newContext("github.com/src-d/proteus/fixtures/erroring/multiple")
18+
assert.NotNil(t, err)
19+
}
20+
21+
func createDirWithMultipleFiles(pkg string) error {
22+
path := filepath.Join(projectDir, pkg)
23+
os.Mkdir(path, os.ModeDir)
24+
25+
f, err := os.Create(filepath.Join(path, "foo.go"))
26+
if err != nil {
27+
return err
28+
}
29+
f.Write([]byte("package foo"))
30+
f.Close()
31+
32+
f, err = os.Create(filepath.Join(path, "bar.go"))
33+
if err != nil {
34+
return err
35+
}
36+
f.Write([]byte("package bar"))
37+
f.Close()
38+
39+
return nil
40+
}
41+
42+
func removeDir(pkg string) {
43+
os.RemoveAll(filepath.Join(projectDir, pkg))
44+
}

scanner/package_test.go

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
package scanner
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
9+
func TestBaseType(t *testing.T) {
10+
typ := newBaseType()
11+
name := "BaseType"
12+
13+
assertRepeatable(t, typ, name)
14+
assertNullable(t, typ, name)
15+
assert.Panics(t, func() { typ.TypeString() }, "does not implement TypeString")
16+
assert.Panics(t, func() { typ.String() }, "does not implement String")
17+
assert.Panics(t, func() { typ.UnqualifiedName() }, "does not implement UnqualifiedName")
18+
}
19+
20+
func TestBasic(t *testing.T) {
21+
typ := NewBasic("basic")
22+
name := "Basic"
23+
24+
assertRepeatable(t, typ, name)
25+
26+
assert.True(t, typ.IsNullable(), "Basic is nullable by default")
27+
typ.SetNullable(false)
28+
assert.True(t, typ.IsNullable(), "Basic cannot be set not nullable")
29+
30+
assert.Equal(t, "basic", typ.String(), "Basic.String returns type's name")
31+
assert.Equal(t, "basic", typ.TypeString(), "Basic.TypeString returns type's name")
32+
assert.Equal(t, "basic", typ.UnqualifiedName(), "Basic.UnqualifiedName returns type's name")
33+
}
34+
35+
func TestNamed_withPath(t *testing.T) {
36+
typ := NewNamed("pkg", "name")
37+
name := "Named (with path)"
38+
39+
assertRepeatable(t, typ, name)
40+
assertNullable(t, typ, name)
41+
42+
assert.Equal(t, "pkg.name", typ.String(), "Named.String() (with path) returns type's name with path")
43+
assert.Equal(t, "pkg.name", typ.TypeString(), "Named.TypeString() (with path) returns type's name with path")
44+
assert.Equal(t, "name", typ.UnqualifiedName(), "Named.UnqualifiedName() (with path) returns type's name without path")
45+
}
46+
47+
func TestNamed_withoutPath(t *testing.T) {
48+
typ := NewNamed("", "name")
49+
name := "Named (without path)"
50+
51+
assertRepeatable(t, typ, name)
52+
assertNullable(t, typ, name)
53+
54+
assert.Equal(t, "name", typ.String(), "Named.String() (with path) returns type's name without path")
55+
assert.Equal(t, "name", typ.TypeString(), "Named.TypeString() (with path) returns type's name without path")
56+
assert.Equal(t, "name", typ.UnqualifiedName(), "Named.UnqualifiedName() (with path) returns type's name without path")
57+
}
58+
59+
func TestAlias_IsNullable(t *testing.T) {
60+
typ := NewAlias(newBaseType(), newBaseType()).(*Alias)
61+
62+
assert.False(t, typ.IsNullable(), "Alias is not nullable if neither the type nor the underlying is nullable")
63+
typ.Type.SetNullable(true)
64+
typ.Underlying.SetNullable(false)
65+
assert.True(t, typ.IsNullable(), "Alias is nullable if the type is nullable but the underlying is not")
66+
typ.Type.SetNullable(false)
67+
typ.Underlying.SetNullable(true)
68+
assert.True(t, typ.IsNullable(), "Alias is nullable if the type is not nullable but the underlying is")
69+
typ.Type.SetNullable(true)
70+
typ.Underlying.SetNullable(true)
71+
assert.True(t, typ.IsNullable(), "Alias is nullable if both the type and the underlying are")
72+
}
73+
74+
func TestAlias_IsRepeated(t *testing.T) {
75+
typ := NewAlias(newBaseType(), newBaseType()).(*Alias)
76+
77+
assert.False(t, typ.IsRepeated(), "Alias is not repeated if neither the type nor the underlying is repeated")
78+
79+
typ.Type.SetRepeated(true)
80+
typ.Underlying.SetRepeated(false)
81+
assert.True(t, typ.IsRepeated(), "Alias is repeated if the type is repeated but the underlying is not")
82+
typ.Type.SetRepeated(false)
83+
typ.Underlying.SetRepeated(true)
84+
assert.True(t, typ.IsRepeated(), "Alias is repeated if the type is not repeated but the underlying is")
85+
typ.Type.SetRepeated(true)
86+
typ.Underlying.SetRepeated(true)
87+
assert.True(t, typ.IsRepeated(), "Alias is repeated if both the type and the underlying are")
88+
}
89+
90+
func TestAlias_stringMethods(t *testing.T) {
91+
typ := NewAlias(NewNamed("", "Aliasing"), NewBasic("string"))
92+
93+
assert.Equal(t, "type Aliasing string", typ.String(), "Alias.String returns a type declaration for the alias")
94+
assert.Equal(t, "Aliasing", typ.TypeString(), "Alias.TypeString returns the type string for the alias")
95+
assert.Equal(t, "Aliasing", typ.UnqualifiedName(), "Alias.UnqualifiedName returns the unqualified name of the alias")
96+
}
97+
98+
func TestMap(t *testing.T) {
99+
typ := NewMap(NewBasic("string"), NewBasic("int"))
100+
name := "Map"
101+
102+
assertRepeatable(t, typ, name)
103+
assertNullable(t, typ, name)
104+
assert.Equal(t, "map[string]int", typ.String(), "Map.String returns a map signature")
105+
assert.Equal(t, "map[string]int", typ.TypeString(), "Map.TypeString returns a map signature")
106+
assert.Equal(t, "map[string]int", typ.UnqualifiedName(), "Map.UnqualifiedName returns a map signature")
107+
}
108+
109+
// assertRepeatable asserts a type respond as expected to IsRepeated and SetRepeated.
110+
func assertRepeatable(t *testing.T, typ Type, name string) {
111+
assert.False(t, typ.IsRepeated(), "%s is not repeated by default", name)
112+
typ.SetRepeated(true)
113+
assert.True(t, typ.IsRepeated(), "%s can be set as repeated", name)
114+
typ.SetRepeated(false)
115+
assert.False(t, typ.IsRepeated(), "%s can be set as not repeated", name)
116+
}
117+
118+
// assertNullable asserts a type responds as expected to IsNullable and SetNullable.
119+
func assertNullable(t *testing.T, typ Type, name string) {
120+
assert.False(t, typ.IsNullable(), "%s is not nullable by default", name)
121+
typ.SetNullable(true)
122+
assert.True(t, typ.IsNullable(), "%s can be set as nullable", name)
123+
typ.SetNullable(false)
124+
assert.False(t, typ.IsNullable(), "%s can be set as not nullable", name)
125+
}

scanner/scanner.go

+7-6
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import (
1111
"sync"
1212

1313
"github.com/src-d/proteus/report"
14-
"github.com/src-d/proteus/source"
14+
15+
"gopkg.in/src-d/go-parse-utils.v1"
1516
)
1617

1718
var goPath = os.Getenv("GOPATH")
@@ -20,7 +21,7 @@ var goPath = os.Getenv("GOPATH")
2021
// and extract types and structs from.
2122
type Scanner struct {
2223
packages []string
23-
importer *source.Importer
24+
importer *parseutil.Importer
2425
}
2526

2627
// ErrNoGoPathSet is the error returned when the GOPATH variable is not
@@ -47,7 +48,7 @@ func New(packages ...string) (*Scanner, error) {
4748

4849
return &Scanner{
4950
packages: packages,
50-
importer: source.NewImporter(),
51+
importer: parseutil.NewImporter(),
5152
}, nil
5253
}
5354

@@ -89,11 +90,11 @@ func (s *Scanner) Scan() ([]*Package, error) {
8990
func (s *Scanner) scanPackage(p string) (*Package, error) {
9091
pkg, err := s.importer.ImportWithFilters(
9192
p,
92-
source.FileFilters{
93-
func(pkg, file string, typ source.FileType) bool {
93+
parseutil.FileFilters{
94+
func(pkg, file string, typ parseutil.FileType) bool {
9495
return !strings.HasSuffix(file, ".pb.go")
9596
},
96-
func(pkg, file string, typ source.FileType) bool {
97+
func(pkg, file string, typ parseutil.FileType) bool {
9798
return !strings.HasSuffix(file, ".proteus.go")
9899
},
99100
},

0 commit comments

Comments
 (0)