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  }