blob: f2a63b05eb307c350c20bc885e1f8140af8b2a38 [file]
package utils_test
import (
"github.com/apache/cloudberry-backup/utils"
"github.com/apache/cloudberry-go-libs/testhelper"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
var _ = Describe("utils/util tests", func() {
Context("DollarQuoteString", func() {
It("uses $$ if the string contains no dollar signs", func() {
testStr := "message"
expected := "$$message$$"
actual := utils.DollarQuoteString(testStr)
Expect(actual).To(Equal(expected))
})
It("uses $_$ if the string contains $", func() {
testStr := "message$text"
expected := "$_$message$text$_$"
actual := utils.DollarQuoteString(testStr)
Expect(actual).To(Equal(expected))
})
It("uses $_X$ if the string contains $_", func() {
testStr := "message$_text"
expected := "$_X$message$_text$_X$"
actual := utils.DollarQuoteString(testStr)
Expect(actual).To(Equal(expected))
})
It("uses $_$ if the string contains non-adjacent $ and _", func() {
testStr := "message$text_"
expected := "$_$message$text_$_$"
actual := utils.DollarQuoteString(testStr)
Expect(actual).To(Equal(expected))
})
})
Describe("ValidateFQNs", func() {
It("validates the following cases correctly", func() {
testStrings := []string{
`schemaname.tablename`, // unquoted
`"schema,name".tablename`, // quoted schema
`schemaname."table,name"`, // quoted table
`schema name.tablename"`, // spaces
`schema name .tablename"`, //tabs
`schemaname.TABLENAME!@#$%^&*()_+={}|[]\';":/,?><"`, // special characters
}
utils.ValidateFQNs(testStrings)
})
It("fails if given a string without a schema", func() {
testStrings := []string{`.tablename`}
err := utils.ValidateFQNs(testStrings)
Expect(err).To(HaveOccurred())
})
It("fails if given a string without a table", func() {
testStrings := []string{`schemaname.`}
err := utils.ValidateFQNs(testStrings)
Expect(err).To(HaveOccurred())
})
It("fails if the schema and table can't be determined", func() {
testStrings := []string{`schemanametablename`}
err := utils.ValidateFQNs(testStrings)
Expect(err).To(HaveOccurred())
})
})
Context("ValidateFullPath", func() {
It("does not return error when the flag is not set", func() {
path := ""
Expect(utils.ValidateFullPath(path)).To(Succeed())
})
It("does not return error when given an absolute path", func() {
path := "/this/is/an/absolute/path"
Expect(utils.ValidateFullPath(path)).To(Succeed())
})
It("panics when given a relative path", func() {
path := "this/is/a/relative/path"
err := utils.ValidateFullPath(path)
Expect(err).To(MatchError("this/is/a/relative/path is not an absolute path."))
})
})
Describe("ValidateGPDBVersionCompatibility", func() {
It("panics if GPDB 5 version is less than 5.1.0", func() {
testhelper.SetDBVersion(connectionPool, "5.0.0")
defer testhelper.ShouldPanicWithMessage("GPDB version 5.0.0 is not supported. Please upgrade to GPDB 5.1.0 or later.")
utils.ValidateGPDBVersionCompatibility(connectionPool)
})
It("does not panic if GPDB version is at least 5.1.0", func() {
testhelper.SetDBVersion(connectionPool, "5.1.0")
utils.ValidateGPDBVersionCompatibility(connectionPool)
})
It("does not panic if GPDB version is at least 6.0.0", func() {
testhelper.SetDBVersion(connectionPool, "6.0.0")
utils.ValidateGPDBVersionCompatibility(connectionPool)
})
})
Describe("ValidateCompressionTypeAndLevel", func() {
It("validates a compression type 'gzip' and a level between 1 and 9", func() {
compressType := "gzip"
compressLevel := 5
err := utils.ValidateCompressionTypeAndLevel(compressType, compressLevel)
Expect(err).To(Not(HaveOccurred()))
})
It("panics if given a compression type 'gzip' and a compression level < 1", func() {
compressType := "gzip"
compressLevel := 0
err := utils.ValidateCompressionTypeAndLevel(compressType, compressLevel)
Expect(err).To(MatchError("compression type 'gzip' only allows compression levels between 1 and 9, but the provided level is 0"))
})
It("panics if given a compression type 'gzip' and a compression level > 9", func() {
compressType := "gzip"
compressLevel := 11
err := utils.ValidateCompressionTypeAndLevel(compressType, compressLevel)
Expect(err).To(MatchError("compression type 'gzip' only allows compression levels between 1 and 9, but the provided level is 11"))
})
It("panics if given a compression type 'invalid' and a compression level > 0", func() {
compressType := "invalid"
compressLevel := 1
err := utils.ValidateCompressionTypeAndLevel(compressType, compressLevel)
Expect(err).To(MatchError("unknown compression type 'invalid'"))
})
It("panics if given a compression type 'invalid' and a compression level < 0", func() {
compressType := "invalid"
compressLevel := -1
err := utils.ValidateCompressionTypeAndLevel(compressType, compressLevel)
Expect(err).To(MatchError("unknown compression type 'invalid'"))
})
It("panics if given a compression type '' and a compression level > 0", func() {
compressType := ""
compressLevel := 1
err := utils.ValidateCompressionTypeAndLevel(compressType, compressLevel)
Expect(err).To(MatchError("unknown compression type ''"))
})
It("validates a compression type 'zstd' and a level between 1 and 19", func() {
compressType := "zstd"
compressLevel := 11
err := utils.ValidateCompressionTypeAndLevel(compressType, compressLevel)
Expect(err).To(Not(HaveOccurred()))
})
It("panics if given a compression type 'zstd' and a compression level < 1", func() {
compressType := "zstd"
compressLevel := 0
err := utils.ValidateCompressionTypeAndLevel(compressType, compressLevel)
Expect(err).To(MatchError("compression type 'zstd' only allows compression levels between 1 and 19, but the provided level is 0"))
})
It("panics if given a compression type 'gzip' and a compression level > 19", func() {
compressType := "zstd"
compressLevel := 20
err := utils.ValidateCompressionTypeAndLevel(compressType, compressLevel)
Expect(err).To(MatchError("compression type 'zstd' only allows compression levels between 1 and 19, but the provided level is 20"))
})
})
Describe("UnquoteIdent", func() {
It("returns unchanged ident when passed a single char", func() {
dbname := `a`
resultString := utils.UnquoteIdent(dbname)
Expect(resultString).To(Equal(`a`))
})
It("returns unchanged ident when passed an unquoted ident", func() {
dbname := `test`
resultString := utils.UnquoteIdent(dbname)
Expect(resultString).To(Equal(`test`))
})
It("returns one double quote when passed a double quote", func() {
dbname := `"`
resultString := utils.UnquoteIdent(dbname)
Expect(resultString).To(Equal(`"`))
})
It("returns empty string when passed an empty string", func() {
dbname := ""
resultString := utils.UnquoteIdent(dbname)
Expect(resultString).To(Equal(``))
})
It("properly unquotes an identfier string and unescapes double quotes", func() {
dbname := `"""test"`
resultString := utils.UnquoteIdent(dbname)
Expect(resultString).To(Equal(`"test`))
})
})
Describe("SliceToQuotedString", func() {
It("quotes and joins a slice of strings into a single string", func() {
inputStrings := []string{"string1", "string2", "string3"}
expectedString := "'string1','string2','string3'"
resultString := utils.SliceToQuotedString(inputStrings)
Expect(resultString).To(Equal(expectedString))
})
It("returns an empty string when given an empty slice", func() {
inputStrings := make([]string, 0)
resultString := utils.SliceToQuotedString(inputStrings)
Expect(resultString).To(Equal(""))
})
})
})