cosmos-sdk/x/upgrade/plan/info_test.go

336 lines
10 KiB
Go

package plan
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
)
type InfoTestSuite struct {
suite.Suite
// Home is a temporary directory for use in these tests.
Home string
}
func (s *InfoTestSuite) SetupTest() {
s.Home = s.T().TempDir()
s.T().Logf("Home: [%s]", s.Home)
}
func TestInfoTestSuite(t *testing.T) {
suite.Run(t, new(InfoTestSuite))
}
// saveSrcTestFile saves a TestFile in this test's Home/src directory.
// The full path to the saved file is returned.
func (s InfoTestSuite) saveTestFile(f *TestFile) string {
fullName, err := f.SaveIn(s.Home)
s.Require().NoError(err, "saving test file %s", f.Name)
return fullName
}
func (s InfoTestSuite) TestParseInfo() {
goodJSON := `{"binaries":{"os1/arch1":"url1","os2/arch2":"url2"}}`
binariesWrongJSON := `{"binaries":["foo","bar"]}`
binariesWrongValueJSON := `{"binaries":{"os1/arch1":1,"os2/arch2":2}}`
goodJSONPath := s.saveTestFile(NewTestFile("good.json", goodJSON))
binariesWrongJSONPath := s.saveTestFile(NewTestFile("binaries-wrong.json", binariesWrongJSON))
binariesWrongValueJSONPath := s.saveTestFile(NewTestFile("binaries-wrong-value.json", binariesWrongValueJSON))
goodJSONAsInfo := &Info{
Binaries: BinaryDownloadURLMap{
"os1/arch1": "url1",
"os2/arch2": "url2",
},
}
makeInfoStrFuncString := func(val string) func(t *testing.T) string {
return func(t *testing.T) string {
return val
}
}
makeInfoStrFuncURL := func(file string) func(t *testing.T) string {
return func(t *testing.T) string {
return makeFileURL(t, file)
}
}
tests := []struct {
name string
infoStrMaker func(t *testing.T) string
expectedInfo *Info
expectedInError []string
}{
{
name: "json good",
infoStrMaker: makeInfoStrFuncString(goodJSON),
expectedInfo: goodJSONAsInfo,
expectedInError: nil,
},
{
name: "blank string",
infoStrMaker: makeInfoStrFuncString(" "),
expectedInfo: nil,
expectedInError: []string{"plan info must not be blank"},
},
{
name: "json binaries is wrong data type",
infoStrMaker: makeInfoStrFuncString(binariesWrongJSON),
expectedInfo: nil,
expectedInError: []string{"could not parse plan info", "cannot unmarshal array into Go struct field Info.binaries"},
},
{
name: "json wrong data type in binaries value",
infoStrMaker: makeInfoStrFuncString(binariesWrongValueJSON),
expectedInfo: nil,
expectedInError: []string{"could not parse plan info", "cannot unmarshal number into Go struct field Info.binaries"},
},
{
name: "url does not exist",
infoStrMaker: makeInfoStrFuncString("file:///this/file/does/not/exist?checksum=sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"),
expectedInfo: nil,
expectedInError: []string{"could not download url", "file:///this/file/does/not/exist"},
},
{
name: "url good",
infoStrMaker: makeInfoStrFuncURL(goodJSONPath),
expectedInfo: goodJSONAsInfo,
expectedInError: nil,
},
{
name: "url binaries is wrong data type",
infoStrMaker: makeInfoStrFuncURL(binariesWrongJSONPath),
expectedInfo: nil,
expectedInError: []string{"could not parse plan info", "cannot unmarshal array into Go struct field Info.binaries"},
},
{
name: "url wrong data type in binaries value",
infoStrMaker: makeInfoStrFuncURL(binariesWrongValueJSONPath),
expectedInfo: nil,
expectedInError: []string{"could not parse plan info", "cannot unmarshal number into Go struct field Info.binaries"},
},
}
for _, tc := range tests {
s.T().Run(tc.name, func(t *testing.T) {
infoStr := tc.infoStrMaker(t)
actualInfo, actualErr := ParseInfo(infoStr)
if len(tc.expectedInError) > 0 {
require.Error(t, actualErr)
for _, expectedErr := range tc.expectedInError {
assert.Contains(t, actualErr.Error(), expectedErr)
}
} else {
require.NoError(t, actualErr)
}
assert.Equal(t, tc.expectedInfo, actualInfo)
})
}
}
func (s InfoTestSuite) TestInfoValidateFull() {
darwinAMD64File := NewTestFile("darwin_amd64", "#!/usr/bin\necho 'darwin/amd64'\n")
linux386File := NewTestFile("linux_386", "#!/usr/bin\necho 'darwin/amd64'\n")
darwinAMD64Path := s.saveTestFile(darwinAMD64File)
linux386Path := s.saveTestFile(linux386File)
darwinAMD64URL := makeFileURL(s.T(), darwinAMD64Path)
linux386URL := makeFileURL(s.T(), linux386Path)
tests := []struct {
name string
planInfo *Info
errs []string
}{
// Positive test case
{
name: "two good entries",
planInfo: &Info{
Binaries: BinaryDownloadURLMap{
"darwin/amd64": darwinAMD64URL,
"linux/386": linux386URL,
},
},
errs: nil,
},
// a failure from BinaryDownloadURLMap.ValidateBasic
{
name: "empty binaries",
planInfo: &Info{Binaries: BinaryDownloadURLMap{}},
errs: []string{"no \"binaries\" entries found"},
},
// a failure from BinaryDownloadURLMap.CheckURLS
{
name: "url does not exist",
planInfo: &Info{
Binaries: BinaryDownloadURLMap{
"darwin/arm64": "file:///no/such/file/exists/hopefully.zip?checksum=sha256:b5a2c96250612366ea272ffac6d9744aaf4b45aacd96aa7cfcb931ee3b558259",
},
},
errs: []string{"error downloading binary", "darwin/arm64", "no such file or directory"},
},
}
for _, tc := range tests {
s.T().Run(tc.name, func(t *testing.T) {
actualErr := tc.planInfo.ValidateFull("daemon")
if len(tc.errs) > 0 {
require.Error(t, actualErr)
for _, expectedErr := range tc.errs {
assert.Contains(t, actualErr.Error(), expectedErr)
}
} else {
require.NoError(t, actualErr)
}
})
}
}
func (s InfoTestSuite) TestBinaryDownloadURLMapValidateBasic() {
addDummyChecksum := func(url string) string {
return url + "?checksum=sha256:b5a2c96250612366ea272ffac6d9744aaf4b45aacd96aa7cfcb931ee3b558259"
}
tests := []struct {
name string
urlMap BinaryDownloadURLMap
errs []string
}{
{
name: "empty map",
urlMap: BinaryDownloadURLMap{},
errs: []string{"no \"binaries\" entries found"},
},
{
name: "key with empty string",
urlMap: BinaryDownloadURLMap{
"": addDummyChecksum("https://v1.cosmos.network/sdk"),
},
errs: []string{"invalid os/arch", `""`},
},
{
name: "invalid key format",
urlMap: BinaryDownloadURLMap{
"badkey": addDummyChecksum("https://v1.cosmos.network/sdk"),
},
errs: []string{"invalid os/arch", "badkey"},
},
{
name: "any key is valid",
urlMap: BinaryDownloadURLMap{
"any": addDummyChecksum("https://v1.cosmos.network/sdk"),
},
errs: nil,
},
{
name: "os arch key is valid",
urlMap: BinaryDownloadURLMap{
"darwin/amd64": addDummyChecksum("https://v1.cosmos.network/sdk"),
},
errs: nil,
},
{
name: "not a url",
urlMap: BinaryDownloadURLMap{
"isa/url": addDummyChecksum("https://v1.cosmos.network/sdk"),
"nota/url": addDummyChecksum("https://v1.cosmos.network:not-a-port/sdk"),
},
errs: []string{"invalid url", "nota/url", "invalid port"},
},
{
name: "url without checksum",
urlMap: BinaryDownloadURLMap{
"darwin/amd64": "https://v1.cosmos.network/sdk",
},
errs: []string{"invalid url", "darwin/amd64", "missing checksum query parameter"},
},
{
name: "multiple valid entries but one bad url",
urlMap: BinaryDownloadURLMap{
"any": addDummyChecksum("https://v1.cosmos.network/sdk"),
"darwin/amd64": addDummyChecksum("https://v1.cosmos.network/sdk"),
"darwin/arm64": addDummyChecksum("https://v1.cosmos.network/sdk"),
"windows/bad": addDummyChecksum("https://v1.cosmos.network:not-a-port/sdk"),
"linux/386": addDummyChecksum("https://v1.cosmos.network/sdk"),
},
errs: []string{"invalid url", "windows/bad", "invalid port"},
},
{
name: "multiple valid entries but one bad key",
urlMap: BinaryDownloadURLMap{
"any": addDummyChecksum("https://v1.cosmos.network/sdk"),
"darwin/amd64": addDummyChecksum("https://v1.cosmos.network/sdk"),
"badkey": addDummyChecksum("https://v1.cosmos.network/sdk"),
"darwin/arm64": addDummyChecksum("https://v1.cosmos.network/sdk"),
"linux/386": addDummyChecksum("https://v1.cosmos.network/sdk"),
},
errs: []string{"invalid os/arch", "badkey"},
},
}
for _, tc := range tests {
s.T().Run(tc.name, func(t *testing.T) {
actualErr := tc.urlMap.ValidateBasic()
if len(tc.errs) > 0 {
require.Error(t, actualErr)
for _, expectedErr := range tc.errs {
assert.Contains(t, actualErr.Error(), expectedErr)
}
} else {
require.NoError(t, actualErr)
}
})
}
}
func (s InfoTestSuite) TestBinaryDownloadURLMapCheckURLs() {
darwinAMD64File := NewTestFile("darwin_amd64", "#!/usr/bin\necho 'darwin/amd64'\n")
linux386File := NewTestFile("linux_386", "#!/usr/bin\necho 'darwin/amd64'\n")
darwinAMD64Path := s.saveTestFile(darwinAMD64File)
linux386Path := s.saveTestFile(linux386File)
darwinAMD64URL := makeFileURL(s.T(), darwinAMD64Path)
linux386URL := makeFileURL(s.T(), linux386Path)
tests := []struct {
name string
urlMap BinaryDownloadURLMap
errs []string
}{
{
name: "two good entries",
urlMap: BinaryDownloadURLMap{
"darwin/amd64": darwinAMD64URL,
"linux/386": linux386URL,
},
errs: nil,
},
{
name: "url does not exist",
urlMap: BinaryDownloadURLMap{
"darwin/arm64": "file:///no/such/file/exists/hopefully.zip?checksum=sha256:b5a2c96250612366ea272ffac6d9744aaf4b45aacd96aa7cfcb931ee3b558259",
},
errs: []string{"error downloading binary", "darwin/arm64", "no such file or directory"},
},
{
name: "bad checksum",
urlMap: BinaryDownloadURLMap{
"darwin/amd64": "file://" + darwinAMD64Path + "?checksum=sha256:b5a2c96250612366ea272ffac6d9744aaf4b45aacd96aa7cfcb931ee3b558259",
},
errs: []string{"error downloading binary", "darwin/amd64", "Checksums did not match", "b5a2c96250612366ea272ffac6d9744aaf4b45aacd96aa7cfcb931ee3b558259"},
},
}
for _, tc := range tests {
s.T().Run(tc.name, func(t *testing.T) {
actualErr := tc.urlMap.CheckURLs("daemon")
if len(tc.errs) > 0 {
require.Error(t, actualErr)
for _, expectedErr := range tc.errs {
assert.Contains(t, actualErr.Error(), expectedErr)
}
} else {
require.NoError(t, actualErr)
}
})
}
}