Provide integration tests via the key Ditto features - SoftwareUpdatable#182
Conversation
Signed-off-by: Antonia Avramova <[email protected]>
k-gostev
left a comment
There was a problem hiding this comment.
Overall looks very good, I have just a couple of nits
| "testing" | ||
|
|
||
| "os" | ||
| "strings" | ||
|
|
||
| "github.com/eclipse-kanto/container-management/rollouts/api/datatypes" | ||
| "github.com/eclipse-kanto/kanto/integration/util" | ||
| "github.com/eclipse/ditto-clients-golang/protocol" | ||
| "github.com/google/uuid" | ||
|
|
||
| "github.com/stretchr/testify/require" | ||
| "github.com/stretchr/testify/suite" |
There was a problem hiding this comment.
| "testing" | |
| "os" | |
| "strings" | |
| "github.com/eclipse-kanto/container-management/rollouts/api/datatypes" | |
| "github.com/eclipse-kanto/kanto/integration/util" | |
| "github.com/eclipse/ditto-clients-golang/protocol" | |
| "github.com/google/uuid" | |
| "github.com/stretchr/testify/require" | |
| "github.com/stretchr/testify/suite" | |
| "testing" | |
| "os" | |
| "strings" | |
| "github.com/eclipse-kanto/container-management/rollouts/api/datatypes" | |
| "github.com/eclipse-kanto/kanto/integration/util" | |
| "github.com/eclipse/ditto-clients-golang/protocol" | |
| "github.com/google/uuid" | |
| "github.com/stretchr/testify/require" | |
| "github.com/stretchr/testify/suite" |
| actionInstall = "install" | ||
| paramCorID = "correlationId" | ||
| paramForced = "forced" | ||
| validJSONUrl = "https://raw.githubusercontent.com/eclipse-kanto/container-management/main/containerm/pkg/testutil/config/container/valid.json" |
There was a problem hiding this comment.
As per https://github.com/golang/go/wiki/CodeReviewComments#initialisms
| validJSONUrl = "https://raw.githubusercontent.com/eclipse-kanto/container-management/main/containerm/pkg/testutil/config/container/valid.json" | |
| validContainerURL = "https://raw.githubusercontent.com/eclipse-kanto/container-management/main/containerm/pkg/testutil/config/container/valid.json" |
| } | ||
|
|
||
| const ( | ||
| suFeatureID = "SoftwareUpdatable" |
|
|
||
| suite.swUpdatableFeatureURL = util.GetFeatureURL(suite.ctrThingURL, suFeatureID) | ||
|
|
||
| suite.assertCtrFeatureDefinition(suite.swUpdatableFeatureURL, "[\"org.eclipse.hawkbit.swupdatable:SoftwareUpdatable:2.0.0\"]") |
There was a problem hiding this comment.
Please export the necessary constants from here and reuse them.
| filter := fmt.Sprintf("like(resource:path,'/features/%s*')", suFeatureID) | ||
|
|
||
| err := util.SubscribeForWSMessages(suite.Cfg, wsConnection, util.StartSendEvents, filter) |
There was a problem hiding this comment.
| filter := fmt.Sprintf("like(resource:path,'/features/%s*')", suFeatureID) | |
| err := util.SubscribeForWSMessages(suite.Cfg, wsConnection, util.StartSendEvents, filter) | |
| err := util.SubscribeForWSMessages(suite.Cfg, wsConnection, util.StartSendEvents, fmt.Sprintf("like(resource:path,'/features/%s*')", suFeatureID) |
| err = util.ProcessWSMessages(suite.Cfg, wsConnection, func(event *protocol.Envelope) (bool, error) { | ||
| var err error | ||
| if event.Topic.String() == suite.topicModified { | ||
| if event.Path == fmt.Sprintf("/features/%s/properties/status/lastOperation", suFeatureID) { |
There was a problem hiding this comment.
/features/%s/properties/status/ is quite repetitive, could you create a function constructStatusPath(featureID, property string) that constructs the status and use it instead.
| err = suite.removeContainer(createRemoveParams(ctrID)) | ||
| require.NoError(suite.T(), err, "failed to process removing the container") |
There was a problem hiding this comment.
| err = suite.removeContainer(createRemoveParams(ctrID)) | |
| require.NoError(suite.T(), err, "failed to process removing the container") | |
| require.NoError(suite.T(), suite.removeContainer(createRemoveParams(ctrID)), "failed to process removing the container") |
| err := suite.removeContainer(createRemoveParams(ctrID)) | ||
| require.ErrorContains(suite.T(), err, "container with ID = "+ctrID+" does not exist") |
There was a problem hiding this comment.
| err := suite.removeContainer(createRemoveParams(ctrID)) | |
| require.ErrorContains(suite.T(), err, "container with ID = "+ctrID+" does not exist") | |
| require.ErrorContains(suite.T(), suite.removeContainer(createRemoveParams(ctrID)), "container with ID = "+ctrID+" does not exist") |
| err = os.WriteFile(filePath, src, 7777) | ||
| require.NoError(suite.T(), err, "unable to write file with path "+filePath) | ||
|
|
||
| params := createInstallParams(filePath, src, wrongChecksum) | ||
| err = os.Remove(filePath) | ||
| require.NoError(suite.T(), err, "unable to remove file with path "+filePath) | ||
| return params |
There was a problem hiding this comment.
could you try this way?
| err = os.WriteFile(filePath, src, 7777) | |
| require.NoError(suite.T(), err, "unable to write file with path "+filePath) | |
| params := createInstallParams(filePath, src, wrongChecksum) | |
| err = os.Remove(filePath) | |
| require.NoError(suite.T(), err, "unable to remove file with path "+filePath) | |
| return params | |
| require.NoError(suite.T(), os.WriteFile(filePath, src, 7777), "unable to write file with path "+filePath) | |
| defer require.NoError(suite.T(), os.Remove(filePath), "unable to remove file with path "+filePath) | |
| return createInstallParams(filePath, src, wrongChecksum) |
| err = json.Unmarshal(bytes, &ctrImage) | ||
| return fileStat, ctrImage, err |
There was a problem hiding this comment.
| err = json.Unmarshal(bytes, &ctrImage) | |
| return fileStat, ctrImage, err | |
| err = | |
| return fileStat, ctrImage, json.Unmarshal(bytes, &ctrImage) |
Signed-off-by: Antonia Avramova <[email protected]>
Signed-off-by: Antonia Avramova <[email protected]>
| "software": []*datatypes.DependencyDescription{ | ||
| &datatypes.DependencyDescription{ | ||
| Name: ctrID, | ||
| }, | ||
| }, | ||
| } |
There was a problem hiding this comment.
| "software": []*datatypes.DependencyDescription{ | |
| &datatypes.DependencyDescription{ | |
| Name: ctrID, | |
| }, | |
| }, | |
| } | |
| "software": []*datatypes.DependencyDescription{ | |
| { | |
| Name: ctrID, | |
| }, | |
| }, | |
| } |
| require.NoError(suite.T(), err, "failed to subscribe for the %s messages", util.StartSendEvents) | ||
|
|
||
| _, err = util.ExecuteOperation(suite.Cfg, suite.suFeatureURL, "remove", params) | ||
| suite.closeOnError(wsConnection, err, "failed to execute software updatable install for containers with params %v", params) |
There was a problem hiding this comment.
| suite.closeOnError(wsConnection, err, "failed to execute software updatable install for containers with params %v", params) | |
| suite.closeOnError(wsConnection, err, "failed to execute software updatable remove for containers with params %v", params) |
| wsConnection.Close() | ||
| } | ||
| require.Errorf(suite.T(), err, "failed to execute software updatable install for containers with params %v", params) | ||
|
|
| if err != nil { | ||
| return nil, err | ||
| } | ||
| defer response.Body.Close() |
There was a problem hiding this comment.
| if err != nil { | |
| return nil, err | |
| } | |
| defer response.Body.Close() | |
| if err != nil { | |
| return nil, err | |
| } | |
| if response.StatusCode < http.StatusOK || response.StatusCode >= http.StatusMultipleChoices { | |
| return nil, fmt.Errorf("http status code is not in the 2xx range: %v", response.StatusCode) | |
| } | |
| defer response.Body.Close() |
| func (suite *softwareUpdatableSuite) createParameters(wrongChecksum bool) map[string]interface{} { | ||
| src, err := download(validContainerURL) | ||
| require.NoError(suite.T(), err, "unable to download file from url "+validContainerURL) | ||
| splitStr := strings.Split(validContainerURL, "/") | ||
| filePath := "/tmp/" + splitStr[len(splitStr)-1] | ||
| require.NoError(suite.T(), os.WriteFile(filePath, src, 7777), "unable to write file with path "+filePath) | ||
|
|
||
| defer require.NoError(suite.T(), os.Remove(filePath), "unable to remove file with path "+filePath) | ||
| return createInstallParams(filePath, src, wrongChecksum) | ||
| } | ||
|
|
||
| func createInstallParams(filePath string, src []byte, wrongChecksum bool) map[string]interface{} { | ||
| fileInfo, ctrStruct, err := getCtrImageStructure(filePath) | ||
| if err != nil { | ||
| return make(map[string]interface{}) | ||
| } |
There was a problem hiding this comment.
In case of some error related to the file operations the test will fail in a not a user friendly manner
| func (suite *softwareUpdatableSuite) createParameters(wrongChecksum bool) map[string]interface{} { | |
| src, err := download(validContainerURL) | |
| require.NoError(suite.T(), err, "unable to download file from url "+validContainerURL) | |
| splitStr := strings.Split(validContainerURL, "/") | |
| filePath := "/tmp/" + splitStr[len(splitStr)-1] | |
| require.NoError(suite.T(), os.WriteFile(filePath, src, 7777), "unable to write file with path "+filePath) | |
| defer require.NoError(suite.T(), os.Remove(filePath), "unable to remove file with path "+filePath) | |
| return createInstallParams(filePath, src, wrongChecksum) | |
| } | |
| func createInstallParams(filePath string, src []byte, wrongChecksum bool) map[string]interface{} { | |
| fileInfo, ctrStruct, err := getCtrImageStructure(filePath) | |
| if err != nil { | |
| return make(map[string]interface{}) | |
| } | |
| func (suite *softwareUpdatableSuite) createParameters(wrongChecksum bool) map[string]interface{} { | |
| src, err := download(validContainerURL) | |
| require.NoError(suite.T(), err, fmt.Sprintf("unable to download file from url %s", validContainerURL)) | |
| filePath := "valid.json" | |
| require.NoError(suite.T(), os.WriteFile(filePath, src, 0755), "unable to write file with path "+filePath) | |
| fileInfo, ctrStruct, err := getCtrImageStructure(filePath) | |
| require.NoError(suite.T(), err, "unable to create container image struct") | |
| defer require.NoError(suite.T(), os.Remove(filePath), "unable to remove file with path "+filePath) | |
| return createInstallParams(fileInfo, ctrStruct, src, wrongChecksum) | |
| } | |
| func createInstallParams(fileInfo fs.FileInfo, ctrStruct CtrImageStruct, src []byte, wrongChecksum bool) map[string]interface{} { | |
| splitStr := strings.Split(ctrStruct.Image.Name, "/") | |
| swModuleStr := strings.Split(splitStr[len(splitStr)-1], ":") |
Signed-off-by: Antonia Avramova <[email protected]>
[#65] Provide integration tests via the key Ditto features - SoftwareUpdatable
Signed-off-by: Antonia Avramova [email protected]