blob: 11b9200c125e1233528dc5f07a3d8a7850e8573f [file] [log] [blame]
package utils_test
import (
"path/filepath"
"regexp"
"github.com/DATA-DOG/go-sqlmock"
"github.com/blang/vfs"
"github.com/blang/vfs/memfs"
"github.com/greenplum-db/gp-common-go-libs/testhelper"
"github.com/greenplum-db/gpbackup/utils"
"github.com/pkg/errors"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
var _ = Describe("gpexpand_sensor", func() {
const sampleCoordinatorDataDir = "/my_fake_database/demoDataDir-1"
var (
memoryfs vfs.Filesystem
mddPathRow *sqlmock.Rows
tableExistsRow *sqlmock.Rows
)
BeforeEach(func() {
memoryfs = memfs.Create()
mddPathRow = sqlmock.NewRows([]string{"datadir"}).AddRow(sampleCoordinatorDataDir)
tableExistsRow = sqlmock.NewRows([]string{"relname"}).AddRow("some table name")
connectionPool.DBName = "postgres"
})
Context("IsGpexpandRunning", func() {
Describe("happy path", func() {
It("senses when gpexpand is in phase 1, as determined by existence of a file 'gpexpand.status' in coordinator data directory", func() {
mock.ExpectQuery(utils.CoordinatorDataDirQuery).WillReturnRows(mddPathRow)
Expect(vfs.MkdirAll(memoryfs, sampleCoordinatorDataDir, 0755)).To(Succeed())
path := filepath.Join(sampleCoordinatorDataDir, utils.GpexpandStatusFilename)
Expect(vfs.WriteFile(memoryfs, path, []byte{0}, 0400)).To(Succeed())
gpexpandSensor := utils.NewGpexpandSensor(memoryfs, connectionPool)
result, err := gpexpandSensor.IsGpexpandRunning()
Expect(err).ToNot(HaveOccurred())
Expect(result).To(BeTrue())
})
It("senses gpexpand is in phase 2, as determined by database query to postgres database for gpexpand's temporary table", func() {
mock.ExpectQuery(utils.CoordinatorDataDirQuery).WillReturnRows(mddPathRow)
mock.ExpectQuery(regexp.QuoteMeta(utils.GpexpandStatusTableExistsQuery)).WillReturnRows(tableExistsRow)
hasGpexpandPhase2StatusRow := sqlmock.NewRows([]string{"status"}).AddRow("some gpexpand status that is not finished")
mock.ExpectQuery(utils.GpexpandTemporaryTableStatusQuery).WillReturnRows(hasGpexpandPhase2StatusRow)
gpexpandSensor := utils.NewGpexpandSensor(memoryfs, connectionPool)
result, err := gpexpandSensor.IsGpexpandRunning()
Expect(err).ToNot(HaveOccurred())
Expect(result).To(BeTrue())
})
It("senses when all indications are that gpexpand status does not exist", func() {
mock.ExpectQuery(utils.CoordinatorDataDirQuery).WillReturnRows(mddPathRow)
tableDoesNotExistsRow := sqlmock.NewRows([]string{"relname"}).AddRow("")
mock.ExpectQuery(regexp.QuoteMeta(utils.GpexpandStatusTableExistsQuery)).WillReturnRows(tableDoesNotExistsRow)
gpexpandSensor := utils.NewGpexpandSensor(memoryfs, connectionPool)
result, err := gpexpandSensor.IsGpexpandRunning()
Expect(err).ToNot(HaveOccurred())
Expect(result).To(BeFalse())
})
It("senses when gpexpand status indicates stoppage", func() {
mock.ExpectQuery(utils.CoordinatorDataDirQuery).WillReturnRows(mddPathRow)
mock.ExpectQuery(regexp.QuoteMeta(utils.GpexpandStatusTableExistsQuery)).WillReturnRows(tableExistsRow)
finishedGpexpandPhase2StatusRow := sqlmock.NewRows([]string{"status"}).AddRow("EXPANSION STOPPED")
mock.ExpectQuery(utils.GpexpandTemporaryTableStatusQuery).WillReturnRows(finishedGpexpandPhase2StatusRow)
gpexpandSensor := utils.NewGpexpandSensor(memoryfs, connectionPool)
result, err := gpexpandSensor.IsGpexpandRunning()
Expect(err).ToNot(HaveOccurred())
Expect(result).To(BeFalse())
})
It("senses when gpexpand status indicates completion", func() {
mock.ExpectQuery(utils.CoordinatorDataDirQuery).WillReturnRows(mddPathRow)
mock.ExpectQuery(regexp.QuoteMeta(utils.GpexpandStatusTableExistsQuery)).WillReturnRows(tableExistsRow)
finishedGpexpandPhase2StatusRow := sqlmock.NewRows([]string{"status"}).AddRow("EXPANSION COMPLETE")
mock.ExpectQuery(utils.GpexpandTemporaryTableStatusQuery).WillReturnRows(finishedGpexpandPhase2StatusRow)
gpexpandSensor := utils.NewGpexpandSensor(memoryfs, connectionPool)
result, err := gpexpandSensor.IsGpexpandRunning()
Expect(err).ToNot(HaveOccurred())
Expect(result).To(BeFalse())
})
It("senses when gpexpand status indicates completion", func() {
mock.ExpectQuery(utils.CoordinatorDataDirQuery).WillReturnRows(mddPathRow)
mock.ExpectQuery(regexp.QuoteMeta(utils.GpexpandStatusTableExistsQuery)).WillReturnRows(tableExistsRow)
finishedGpexpandPhase2StatusRow := sqlmock.NewRows([]string{"status"}).AddRow("SETUP DONE")
mock.ExpectQuery(utils.GpexpandTemporaryTableStatusQuery).WillReturnRows(finishedGpexpandPhase2StatusRow)
gpexpandSensor := utils.NewGpexpandSensor(memoryfs, connectionPool)
result, err := gpexpandSensor.IsGpexpandRunning()
Expect(err).ToNot(HaveOccurred())
Expect(result).To(BeFalse())
})
})
Describe("sad paths", func() {
It("returns an error when MDD query fails", func() {
mock.ExpectQuery(utils.CoordinatorDataDirQuery).WillReturnError(errors.New("query error"))
gpexpandSensor := utils.NewGpexpandSensor(memoryfs, connectionPool)
_, err := gpexpandSensor.IsGpexpandRunning()
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(Equal("query error"))
})
It("returns an error when Stat for file fails for a reason besides 'does not exist'", func() {
mock.ExpectQuery(utils.CoordinatorDataDirQuery).WillReturnRows(mddPathRow)
gpexpandSensor := utils.NewGpexpandSensor(vfs.Dummy(errors.New("fs error")), connectionPool)
_, err := gpexpandSensor.IsGpexpandRunning()
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(Equal("fs error"))
})
It("returns an error when supplied with a connection to a database != postgres", func() {
connectionPool.DBName = "notThePostgresDatabase"
gpexpandSensor := utils.NewGpexpandSensor(memoryfs, connectionPool)
_, err := gpexpandSensor.IsGpexpandRunning()
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(Equal("gpexpand sensor requires a connection to the postgres database"))
})
It("returns an error when supplied with Greenplum version < 6", func() {
Skip("Test is not applicable to cloudberry 1.0+")
testhelper.SetDBVersion(connectionPool, "5.3.0")
gpexpandSensor := utils.NewGpexpandSensor(memoryfs, connectionPool)
_, err := gpexpandSensor.IsGpexpandRunning()
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(Equal("gpexpand sensor requires a connection to Greenplum version >= 6"))
})
})
})
})