github.com/mweagle/Sparta@v1.15.0/aws/step/step_test.go (about) 1 package step 2 3 import ( 4 "context" 5 "math/rand" 6 "testing" 7 "time" 8 9 sparta "github.com/mweagle/Sparta" 10 spartaCF "github.com/mweagle/Sparta/aws/cloudformation" 11 spartaTesting "github.com/mweagle/Sparta/testing" 12 gocf "github.com/mweagle/go-cloudformation" 13 "github.com/sirupsen/logrus" 14 ) 15 16 func testStepProvisionAssertError(t *testing.T, 17 lambdaFns []*sparta.LambdaAWSInfo, 18 stateMachine *StateMachine) { 19 20 // Add the state machine to the deployment... 21 workflowHooks := &sparta.WorkflowHooks{ 22 ServiceDecorators: []sparta.ServiceDecoratorHookHandler{ 23 stateMachine.StateMachineDecorator(), 24 }, 25 } 26 spartaTesting.ProvisionEx(t, 27 lambdaFns, 28 nil, 29 nil, 30 workflowHooks, 31 false, 32 spartaTesting.AssertError("Failed to reject duplicate named tasks")) 33 } 34 35 func testStepProvision(t *testing.T, 36 lambdaFns []*sparta.LambdaAWSInfo, 37 stateMachine *StateMachine) { 38 39 // Add the state machine to the deployment... 40 workflowHooks := &sparta.WorkflowHooks{ 41 ServiceDecorators: []sparta.ServiceDecoratorHookHandler{ 42 stateMachine.StateMachineDecorator(), 43 }, 44 } 45 spartaTesting.ProvisionEx(t, lambdaFns, nil, nil, workflowHooks, false, nil) 46 } 47 48 // Standard AWS λ function 49 func helloWorld(ctx context.Context, 50 props map[string]interface{}) (map[string]interface{}, error) { 51 sparta.Logger().WithFields(logrus.Fields{ 52 "Woot": "Found", 53 }).Warn("Lambda called") 54 55 return map[string]interface{}{ 56 "hello": "world", 57 }, nil 58 } 59 60 type lambdaRollResponse struct { 61 Roll int `json:"roll"` 62 } 63 64 // Standard AWS λ function 65 func lambdaRollDie(ctx context.Context) (lambdaRollResponse, error) { 66 return lambdaRollResponse{ 67 Roll: rand.Intn(5) + 1, 68 }, nil 69 } 70 71 func TestAWSStepFunction(t *testing.T) { 72 // Normal Sparta lambda function 73 lambdaFn, _ := sparta.NewAWSLambda(sparta.LambdaName(helloWorld), 74 helloWorld, 75 sparta.IAMRoleDefinition{}) 76 77 // // Create a Choice state 78 lambdaTaskState := NewLambdaTaskState("lambdaHelloWorld", lambdaFn) 79 delayState := NewWaitDelayState("holdUpNow", 3*time.Second) 80 successState := NewSuccessState("success") 81 82 // Hook them up.. 83 lambdaTaskState.Next(delayState) 84 delayState.Next(successState) 85 86 // Startup the machine. 87 startMachine := NewStateMachine("SampleStepFunction", lambdaTaskState) 88 89 testStepProvision(t, 90 []*sparta.LambdaAWSInfo{lambdaFn}, 91 startMachine) 92 } 93 94 func TestAWSStepFunctionDuplicateStateName(t *testing.T) { 95 96 // Normal Sparta lambda function 97 lambdaFn, _ := sparta.NewAWSLambda(sparta.LambdaName(helloWorld), 98 helloWorld, 99 sparta.IAMRoleDefinition{}) 100 101 // // Create a Choice state 102 lambdaTaskState := NewLambdaTaskState("task1", lambdaFn) 103 lambdaTaskState2 := NewLambdaTaskState("task1", lambdaFn) 104 successState := NewSuccessState("success") 105 106 // Hook them up.. 107 lambdaTaskState.Next(lambdaTaskState2) 108 lambdaTaskState2.Next(successState) 109 110 // Startup the machine. 111 startMachine := NewStateMachine("DuplicateStatesStepFunction", lambdaTaskState) 112 113 testStepProvisionAssertError(t, 114 []*sparta.LambdaAWSInfo{lambdaFn}, 115 startMachine) 116 } 117 118 func TestRollDieChoice(t *testing.T) { 119 lambdaFn, _ := sparta.NewAWSLambda("StepRollDie", 120 lambdaRollDie, 121 sparta.IAMRoleDefinition{}) 122 123 // Make all the Step states 124 lambdaTaskState := NewLambdaTaskState("lambdaRollDie", lambdaFn) 125 successState := NewSuccessState("success") 126 delayState := NewWaitDelayState("tryAgainShortly", 3*time.Second) 127 lambdaChoices := []ChoiceBranch{ 128 &Not{ 129 Comparison: &NumericGreaterThan{ 130 Variable: "$.roll", 131 Value: 3, 132 }, 133 Next: delayState, 134 }, 135 } 136 choiceState := NewChoiceState("checkRoll", 137 lambdaChoices...). 138 WithDefault(successState) 139 140 // Hook up the transitions 141 lambdaTaskState.Next(choiceState) 142 delayState.Next(lambdaTaskState) 143 144 // Startup the machine. 145 stateMachineName := spartaCF.UserScopedStackName("TestStateMachine") 146 startMachine := NewStateMachine(stateMachineName, lambdaTaskState) 147 148 testStepProvision(t, 149 []*sparta.LambdaAWSInfo{lambdaFn}, 150 startMachine) 151 } 152 153 func TestDynamoDB(t *testing.T) { 154 dynamoDbParams := DynamoDBGetItemParameters{ 155 TableName: gocf.String("MY_TABLE"), 156 AttributesToGet: []string{"attr1", "attr2"}, 157 } 158 dynamoState := NewDynamoDBGetItemState("testState", dynamoDbParams) 159 stateJSON, stateJSONErr := dynamoState.MarshalJSON() 160 if stateJSONErr != nil { 161 t.Fatalf("Failed to create JSON: %s", stateJSONErr) 162 } 163 t.Logf("JSON DATA:\n%s", string(stateJSON)) 164 } 165 166 func createDataLambda(ctx context.Context, 167 props map[string]interface{}) (map[string]interface{}, error) { 168 169 return map[string]interface{}{ 170 "ship-date": "2016-03-14T01:59:00Z", 171 "detail": map[string]interface{}{ 172 "delivery-partner": "UQS", 173 "shipped": []map[string]interface{}{ 174 { 175 "prod": "R31", 176 "dest-code": 9511, 177 "quantity": 1344, 178 }, 179 { 180 "prod": "S39", 181 "dest-code": 9511, 182 "quantity": 40, 183 }, 184 { 185 "prod": "R31", 186 "dest-code": 9833, 187 "quantity": 12, 188 }, 189 { 190 "prod": "R40", 191 "dest-code": 9860, 192 "quantity": 887, 193 }, 194 { 195 "prod": "R40", 196 "dest-code": 9511, 197 "quantity": 1220, 198 }, 199 }, 200 }, 201 }, nil 202 } 203 204 // Standard AWS λ function 205 func applyCallback(ctx context.Context, 206 props map[string]interface{}) (map[string]interface{}, error) { 207 return map[string]interface{}{ 208 "Message": "Hello", 209 "Event": props, 210 }, nil 211 } 212 213 func TestMapState(t *testing.T) { 214 // Make the Map state 215 lambdaMapFn, _ := sparta.NewAWSLambda("mapLambdaCallback", 216 applyCallback, 217 sparta.IAMRoleDefinition{}) 218 lambdaMapTaskState := NewLambdaTaskState("lambdaMapData", lambdaMapFn) 219 mapMachine := NewStateMachine("mapStateName", lambdaMapTaskState) 220 mapState := NewMapState("mapResults", mapMachine) 221 successState := NewSuccessState("success") 222 mapState.Next(successState) 223 224 // Then the start state to produce some data 225 lambdaProducerFn, _ := sparta.NewAWSLambda("produceData", 226 createDataLambda, 227 sparta.IAMRoleDefinition{}) 228 lambdaProducerTaskState := NewLambdaTaskState("lambdaProduceData", lambdaProducerFn) 229 230 // Hook up the transitions 231 stateMachineName := spartaCF.UserScopedStackName("TestMapStateMachine") 232 lambdaProducerTaskState.Next(mapState) 233 stateMachine := NewStateMachine(stateMachineName, lambdaProducerTaskState) 234 // Startup the machine. 235 testStepProvision(t, 236 []*sparta.LambdaAWSInfo{lambdaMapFn, lambdaProducerFn}, 237 stateMachine) 238 } 239 240 func TestParallelState(t *testing.T) { 241 // Make the Map state 242 lambdaMapFn, _ := sparta.NewAWSLambda("parallelLambdaCallback", 243 applyCallback, 244 sparta.IAMRoleDefinition{}) 245 lambdaMapTaskState := NewLambdaTaskState("lambdaMapData", lambdaMapFn) 246 parallelMachine := NewStateMachine("mapStateName", lambdaMapTaskState) 247 parallelState := NewParallelState("mapResults", parallelMachine) 248 successState := NewSuccessState("success") 249 parallelState.Next(successState) 250 251 // Then the start state to produce some data 252 lambdaProducerFn, _ := sparta.NewAWSLambda("produceData", 253 createDataLambda, 254 sparta.IAMRoleDefinition{}) 255 lambdaProducerTaskState := NewLambdaTaskState("lambdaProduceData", lambdaProducerFn) 256 257 // Hook up the transitions 258 stateMachineName := spartaCF.UserScopedStackName("TestParallelStateMachine") 259 lambdaProducerTaskState.Next(parallelState) 260 stateMachine := NewStateMachine(stateMachineName, lambdaProducerTaskState) 261 // Startup the machine. 262 testStepProvision(t, 263 []*sparta.LambdaAWSInfo{lambdaMapFn, lambdaProducerFn}, 264 stateMachine) 265 }