Skip to content

Commit

Permalink
fix #245 Reload() functions leaks connection
Browse files Browse the repository at this point in the history
Add some tests for generated store functions to check connections are
leaked or not.
  • Loading branch information
kamichidu committed May 29, 2018
1 parent cf0ccd9 commit c4daf22
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 0 deletions.
1 change: 1 addition & 0 deletions store.go
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,7 @@ func (s *Store) Reload(schema Schema, record Record) error {
if err != nil {
return err
}
defer rows.Close()

rs := NewResultSet(rows, false, nil, columns...)
if !rs.Next() {
Expand Down
36 changes: 36 additions & 0 deletions tests/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ type BaseTestSuite struct {
db *sql.DB
schemas []string
tables []string

// the count of opened connections.
// this will be set in the SetupTest function.
openConnectionsBeforeTest int
}

func NewBaseSuite(schemas []string, tables ...string) BaseTestSuite {
Expand All @@ -41,6 +45,11 @@ func (s *BaseTestSuite) SetupSuite() {
panic(fmt.Sprintf("It was unable to connect to the DB.\n%s\n", err))
}

// set all connections will be closed immediately.
// this is required to check connections are leaked or not.
// because database/sql keep connection in the pool by default.
db.SetMaxIdleConns(0)

s.db = db
}

Expand All @@ -49,6 +58,9 @@ func (s *BaseTestSuite) TearDownSuite() {
}

func (s *BaseTestSuite) SetupTest() {
// save current open connection count for detecting that connection was leaked while a test.
s.openConnectionsBeforeTest = s.db.Stats().OpenConnections

if len(s.tables) == 0 {
return
}
Expand All @@ -57,6 +69,12 @@ func (s *BaseTestSuite) SetupTest() {
}

func (s *BaseTestSuite) TearDownTest() {
openConnections := s.db.Stats().OpenConnections
leakedConnections := openConnections - s.openConnectionsBeforeTest
if leakedConnections > 0 {
s.Fail(fmt.Sprintf("%d database connections were leaked", leakedConnections))
}

if len(s.tables) == 0 {
return
}
Expand Down Expand Up @@ -113,6 +131,24 @@ func (s *BaseTestSuite) resultOrError(res interface{}, err error) bool {
return true
}

func (s *BaseTestSuite) resultsOrError(res interface{}, err error) bool {
if reflect.ValueOf(res).Kind() != reflect.Slice {
panic("resultsOrError expects res is a slice")
}

if err == nil && res == nil {
s.Fail("FindAll should return an error or a documents, but nothing was returned")
return false
}

if err != nil && res != nil {
s.Fail("FindAll should return only an error or a documents, but it was returned both")
return false
}

return true
}

func envOrDefault(key string, def string) string {
v := os.Getenv(key)
if v == "" {
Expand Down
1 change: 1 addition & 0 deletions tests/resultset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ func (s *ResulsetSuite) TestResultSetForEachError() {

s.NotPanics(func() {
rs := store.MustFind(NewResultSetFixtureQuery())
defer rs.Close()
err := rs.ForEach(func(*ResultSetFixture) error {
return fail
})
Expand Down
59 changes: 59 additions & 0 deletions tests/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ func (s *StoreSuite) TestStoreMustFind() {
query := NewStoreFixtureQuery()
s.NotPanics(func() {
rs := store.MustFind(query)
defer rs.Close()
s.NotNil(rs)
})
}
Expand All @@ -111,6 +112,64 @@ func (s *StoreSuite) TestStoreFindOneReturnValues() {
s.resultOrError(doc, err)
}

func (s *StoreSuite) TestStoreFindAllReturnValues() {
store := NewStoreWithConstructFixtureStore(s.db)
s.Nil(store.Insert(NewStoreWithConstructFixture("foo")))
s.Nil(store.Insert(NewStoreWithConstructFixture("bar")))

notFoundQuery := NewStoreWithConstructFixtureQuery()
notFoundQuery.Where(kallax.Eq(Schema.ResultSetFixture.ID, kallax.NewULID()))
docs, err := store.FindAll(notFoundQuery)
s.resultsOrError(docs, err)
s.NotPanics(func() {
s.Equal(0, len(docs))
})

docs, err = store.FindAll(NewStoreWithConstructFixtureQuery().Order(kallax.Asc(Schema.StoreWithConstructFixture.Foo)))
s.resultsOrError(docs, err)
s.NotPanics(func() {
s.Equal(2, len(docs))
s.Equal("bar", docs[0].Foo)
s.Equal("foo", docs[1].Foo)
})
}

func (s *StoreSuite) TestStoreCount() {
store := NewStoreWithConstructFixtureStore(s.db)
s.Nil(store.Insert(NewStoreWithConstructFixture("foo")))
s.Nil(store.Insert(NewStoreWithConstructFixture("bar")))

notFoundQuery := NewStoreWithConstructFixtureQuery()
notFoundQuery.Where(kallax.Eq(Schema.ResultSetFixture.ID, kallax.NewULID()))
count, err := store.Count(notFoundQuery)
s.Nil(err)
s.NotPanics(func() {
s.Equal(int64(0), count)
})

count, err = store.Count(NewStoreWithConstructFixtureQuery())
s.Nil(err)
s.NotPanics(func() {
s.Equal(int64(2), count)
})
}

func (s *StoreSuite) TestStoreReload() {
store := NewStoreWithConstructFixtureStore(s.db)
s.Nil(store.Insert(NewStoreWithConstructFixture("bar")))

doc, err := store.FindOne(NewStoreWithConstructFixtureQuery().FindByFoo("bar").Select(Schema.StoreWithConstructFixture.ID))
s.Nil(err)
s.NotPanics(func() {
s.Equal("", doc.Foo)
})
err = store.Reload(doc)
s.Nil(err)
s.NotPanics(func() {
s.Equal("bar", doc.Foo)
})
}

func (s *StoreSuite) TestStoreInsertUpdateMustFind() {
store := NewStoreWithConstructFixtureStore(s.db)

Expand Down

0 comments on commit c4daf22

Please sign in to comment.