175 lines
3.2 KiB
Go
175 lines
3.2 KiB
Go
package pg_test
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/go-pg/pg"
|
|
|
|
. "github.com/onsi/ginkgo"
|
|
. "github.com/onsi/gomega"
|
|
)
|
|
|
|
func concurrency() (int, int) {
|
|
if testing.Short() {
|
|
return 4, 100
|
|
}
|
|
return 10, 1000
|
|
}
|
|
|
|
var _ = Describe("DB timeout race", func() {
|
|
var db *pg.DB
|
|
var C, N int
|
|
|
|
BeforeEach(func() {
|
|
C, N = concurrency()
|
|
N = 100
|
|
})
|
|
|
|
AfterEach(func() {
|
|
pool := db.Pool()
|
|
Expect(pool.Len()).To(Equal(0))
|
|
Expect(pool.FreeLen()).To(Equal(0))
|
|
|
|
err := db.Close()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
// Give Postgres some time to recover.
|
|
time.Sleep(time.Second)
|
|
})
|
|
|
|
test := func() {
|
|
It("is race free", func() {
|
|
perform(C, func(id int) {
|
|
for i := 0; i < N; i++ {
|
|
_, err := db.Exec("SELECT pg_sleep(1)")
|
|
Expect(err).To(HaveOccurred())
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
Describe("dial timeout", func() {
|
|
BeforeEach(func() {
|
|
opt := pgOptions()
|
|
opt.DialTimeout = time.Nanosecond
|
|
db = pg.Connect(opt)
|
|
})
|
|
|
|
test()
|
|
})
|
|
|
|
Describe("read timeout", func() {
|
|
BeforeEach(func() {
|
|
opt := pgOptions()
|
|
opt.ReadTimeout = time.Nanosecond
|
|
db = pg.Connect(opt)
|
|
})
|
|
|
|
test()
|
|
})
|
|
|
|
Describe("write timeout", func() {
|
|
BeforeEach(func() {
|
|
opt := pgOptions()
|
|
opt.WriteTimeout = time.Nanosecond
|
|
db = pg.Connect(opt)
|
|
})
|
|
|
|
test()
|
|
})
|
|
})
|
|
|
|
var _ = Describe("DB race", func() {
|
|
var db *pg.DB
|
|
var C, N int
|
|
|
|
BeforeEach(func() {
|
|
db = pg.Connect(pgOptions())
|
|
|
|
err := createTestSchema(db)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
C, N = concurrency()
|
|
})
|
|
|
|
AfterEach(func() {
|
|
err := db.Close()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
It("invalid Scan is race free", func() {
|
|
perform(C, func(id int) {
|
|
for i := 0; i < N; i++ {
|
|
var n int
|
|
if i%2 == 0 {
|
|
_, err := db.QueryOne(pg.Scan(&n), "SELECT 1, 2")
|
|
Expect(err).To(HaveOccurred())
|
|
} else {
|
|
_, err := db.QueryOne(pg.Scan(&n), "SELECT 123")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(n).To(Equal(123))
|
|
}
|
|
}
|
|
})
|
|
})
|
|
|
|
It("SelectOrInsert with OnConflict is race free", func() {
|
|
perform(C, func(id int) {
|
|
a := &Author{
|
|
Name: "R. Scott Bakker",
|
|
}
|
|
for i := 0; i < N; i++ {
|
|
a.ID = 0
|
|
_, err := db.Model(a).
|
|
Column("id").
|
|
Where("name = ?name").
|
|
OnConflict("DO NOTHING").
|
|
Returning("id").
|
|
SelectOrInsert(&a.ID)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(a.ID).NotTo(BeZero())
|
|
|
|
if i%(N/C) == 0 {
|
|
err := db.Delete(a)
|
|
if err != pg.ErrNoRows {
|
|
Expect(err).NotTo(HaveOccurred())
|
|
}
|
|
}
|
|
}
|
|
})
|
|
|
|
count, err := db.Model(&Author{}).Count()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(count).To(Equal(1))
|
|
})
|
|
|
|
It("SelectOrInsert without OnConflict is race free", func() {
|
|
perform(C, func(id int) {
|
|
a := &Author{
|
|
Name: "R. Scott Bakker",
|
|
}
|
|
for i := 0; i < N; i++ {
|
|
a.ID = 0
|
|
_, err := db.Model(a).
|
|
Column("id").
|
|
Where("name = ?name").
|
|
Returning("id").
|
|
SelectOrInsert(&a.ID)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(a.ID).NotTo(BeZero())
|
|
|
|
if i%(N/C) == 0 {
|
|
err := db.Delete(a)
|
|
if err != pg.ErrNoRows {
|
|
Expect(err).NotTo(HaveOccurred())
|
|
}
|
|
}
|
|
}
|
|
})
|
|
|
|
count, err := db.Model(&Author{}).Count()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(count).To(Equal(1))
|
|
})
|
|
})
|