// Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the // License is located at // // http://aws.amazon.com/apache2.0/ // // or in the "license" file accompanying this file. This file is distributed // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, // either express or implied. See the License for the specific language governing // permissions and limitations under the License. // Package executer provides interfaces as document execution logic package basicexecuter import ( "testing" "github.com/aws/amazon-ssm-agent/agent/context" "github.com/aws/amazon-ssm-agent/agent/contracts" executermock "github.com/aws/amazon-ssm-agent/agent/framework/processor/executer/mock" contextmocks "github.com/aws/amazon-ssm-agent/agent/mocks/context" "github.com/aws/amazon-ssm-agent/agent/mocks/log" "github.com/aws/amazon-ssm-agent/agent/task" "github.com/stretchr/testify/assert" ) var logger = log.NewMockLog() type TestCase struct { // Msg stores a parsed MDS message as received from GetMessages. MsgId string // DocState stores parsed Document State DocState contracts.DocumentState // PluginResults stores the (unmarshalled) results that the plugins are expected to produce. PluginResults map[string]*contracts.PluginResult //Result ResultStatus contracts.ResultStatus } // TestBasicExecuter test the execution of a given document // with the correct response. func TestBasicExecuter(t *testing.T) { docInfo := contracts.DocumentInfo{ CreatedDate: "2017-06-10T01-23-07.853Z", CommandID: "13e8e6ad-e195-4ccb-86ee-328153b0dafe", MessageID: "MessageID", DocumentName: "AWS-RunPowerShellScript", InstanceID: "i-400e1090", RunCount: 0, } pluginState := contracts.PluginState{ Name: "aws:runScript", Id: "plugin1", } docState := contracts.DocumentState{ DocumentInformation: docInfo, DocumentType: "SendCommand", InstancePluginsInformation: []contracts.PluginState{pluginState}, } result := contracts.PluginResult{ PluginID: "plugin1", PluginName: "aws:runScript", Status: contracts.ResultStatusSuccess, } results := make(map[string]*contracts.PluginResult) results[pluginState.Id] = &result //form test case testCase := TestCase{ MsgId: "aws.ssm.13e8e6ad-e195-4ccb-86ee-328153b0dafe.i-400e1090", DocState: docState, PluginResults: results, ResultStatus: contracts.ResultStatusSuccess, } testBasicExecuter(t, testCase) } func testBasicExecuter(t *testing.T, testCase TestCase) { cancelFlag := task.NewChanneledCancelFlag() nPlugins := len(testCase.DocState.InstancePluginsInformation) // call method under test //orchestrationRootDir is set to empty such that it can meet the test expectation. e := NewBasicExecuter(contextmocks.NewMockDefault()) nStatusReceived := 0 state := testCase.DocState dataStoreMock := new(executermock.MockDocumentStore) resultState := state resultState.DocumentInformation.DocumentStatus = testCase.ResultStatus resultState.InstancePluginsInformation[0].Result = *testCase.PluginResults["plugin1"] dataStoreMock.On("Load").Return(state) dataStoreMock.On("Save", resultState).Return() pluginRunner = func(context context.T, docState contracts.DocumentState, resChan chan contracts.PluginResult, cancelFlag task.CancelFlag) map[string]*contracts.PluginResult { outputs := make(map[string]*contracts.PluginResult) for _, pluginState := range testCase.DocState.InstancePluginsInformation { resChan <- *testCase.PluginResults[pluginState.Id] outputs[pluginState.Id] = testCase.PluginResults[pluginState.Id] } return outputs } resChan := e.Run(cancelFlag, dataStoreMock) done := false for res := range resChan { if done { assert.FailNow(t, "response channel is not closed") } //receive overall results if res.LastPlugin == "" { //all individual plugin has finished execution assert.Equal(t, nStatusReceived, nPlugins) assert.Equal(t, res.Status, testCase.ResultStatus) assert.Equal(t, res.PluginResults, testCase.PluginResults) assert.Equal(t, "MessageID", res.MessageID) //assert channel close last done = true continue } curPlugin := testCase.DocState.InstancePluginsInformation[nStatusReceived].Id //assert plugin execution order assert.Equal(t, curPlugin, res.LastPlugin) //assert message id assert.Equal(t, "MessageID", res.MessageID) nStatusReceived++ //Assert the number of plugins have been updated assert.Equal(t, len(res.PluginResults), nStatusReceived) //Assert the specific latest plugin is updated assert.Equal(t, res.PluginResults[res.LastPlugin], testCase.PluginResults[res.LastPlugin]) } //assert transaction has completed assert.True(t, done) dataStoreMock.AssertExpectations(t) }