diff --git a/flytepropeller/pkg/apis/flyteworkflow/v1alpha1/array_test.go b/flytepropeller/pkg/apis/flyteworkflow/v1alpha1/array_test.go new file mode 100644 index 0000000000..74ea26a428 --- /dev/null +++ b/flytepropeller/pkg/apis/flyteworkflow/v1alpha1/array_test.go @@ -0,0 +1,49 @@ +package v1alpha1 + +import ( + "testing" +) + +func TestArrayNodeSpec_GetSubNodeSpec(t *testing.T) { + nodeSpec := &NodeSpec{} + arrayNodeSpec := ArrayNodeSpec{ + SubNodeSpec: nodeSpec, + } + + if arrayNodeSpec.GetSubNodeSpec() != nodeSpec { + t.Errorf("Expected nodeSpec, but got a different value") + } +} + +func TestArrayNodeSpec_GetParallelism(t *testing.T) { + parallelism := uint32(5) + arrayNodeSpec := ArrayNodeSpec{ + Parallelism: parallelism, + } + + if arrayNodeSpec.GetParallelism() != parallelism { + t.Errorf("Expected %d, but got %d", parallelism, arrayNodeSpec.GetParallelism()) + } +} + +func TestArrayNodeSpec_GetMinSuccesses(t *testing.T) { + minSuccesses := uint32(3) + arrayNodeSpec := ArrayNodeSpec{ + MinSuccesses: &minSuccesses, + } + + if *arrayNodeSpec.GetMinSuccesses() != minSuccesses { + t.Errorf("Expected %d, but got %d", minSuccesses, *arrayNodeSpec.GetMinSuccesses()) + } +} + +func TestArrayNodeSpec_GetMinSuccessRatio(t *testing.T) { + minSuccessRatio := float32(0.8) + arrayNodeSpec := ArrayNodeSpec{ + MinSuccessRatio: &minSuccessRatio, + } + + if *arrayNodeSpec.GetMinSuccessRatio() != minSuccessRatio { + t.Errorf("Expected %f, but got %f", minSuccessRatio, *arrayNodeSpec.GetMinSuccessRatio()) + } +} diff --git a/flytepropeller/pkg/apis/flyteworkflow/v1alpha1/branch_test.go b/flytepropeller/pkg/apis/flyteworkflow/v1alpha1/branch_test.go index d5adf91d77..5fe19f6758 100644 --- a/flytepropeller/pkg/apis/flyteworkflow/v1alpha1/branch_test.go +++ b/flytepropeller/pkg/apis/flyteworkflow/v1alpha1/branch_test.go @@ -1,20 +1,21 @@ -package v1alpha1_test +package v1alpha1 import ( + "bytes" "encoding/json" "io/ioutil" "testing" + "github.com/golang/protobuf/jsonpb" "github.com/stretchr/testify/assert" "github.com/flyteorg/flyte/flyteidl/gen/pb-go/flyteidl/core" - "github.com/flyteorg/flyte/flytepropeller/pkg/apis/flyteworkflow/v1alpha1" ) func TestMarshalUnMarshal_BranchTask(t *testing.T) { r, err := ioutil.ReadFile("testdata/branch.json") assert.NoError(t, err) - o := v1alpha1.NodeSpec{} + o := NodeSpec{} err = json.Unmarshal(r, &o) assert.NoError(t, err) assert.NotNil(t, o.BranchNode.If) @@ -25,3 +26,74 @@ func TestMarshalUnMarshal_BranchTask(t *testing.T) { assert.NotEmpty(t, raw) } } + +// TestBranchNodeSpecMethods tests the methods of the BranchNodeSpec struct. +func TestErrorMarshalAndUnmarshalJSON(t *testing.T) { + coreError := &core.Error{ + FailedNodeId: "TestNode", + Message: "Test error message", + } + + err := Error{Error: coreError} + data, jErr := err.MarshalJSON() + assert.Nil(t, jErr) + + // Unmarshalling the JSON back to a new core.Error struct + var newCoreError core.Error + uErr := jsonpb.Unmarshal(bytes.NewReader(data), &newCoreError) + assert.Nil(t, uErr) + assert.Equal(t, coreError.Message, newCoreError.Message) + assert.Equal(t, coreError.FailedNodeId, newCoreError.FailedNodeId) +} + +func TestBranchNodeSpecMethods(t *testing.T) { + // Creating a core.BooleanExpression instance for testing + boolExpr := &core.BooleanExpression{} + + // Creating an Error instance for testing + errorMessage := &core.Error{ + Message: "Test error", + } + + ifNode := NodeID("ifNode") + elifNode := NodeID("elifNode") + elseNode := NodeID("elseNode") + + // Creating a BranchNodeSpec instance for testing + branchNodeSpec := BranchNodeSpec{ + If: IfBlock{ + Condition: BooleanExpression{ + BooleanExpression: boolExpr, + }, + ThenNode: &ifNode, + }, + ElseIf: []*IfBlock{ + { + Condition: BooleanExpression{ + BooleanExpression: boolExpr, + }, + ThenNode: &elifNode, + }, + }, + Else: &elseNode, + ElseFail: &Error{Error: errorMessage}, + } + + assert.Equal(t, boolExpr, branchNodeSpec.If.GetCondition()) + + assert.Equal(t, &ifNode, branchNodeSpec.If.GetThenNode()) + + assert.Equal(t, &branchNodeSpec.If, branchNodeSpec.GetIf()) + + assert.Equal(t, &elseNode, branchNodeSpec.GetElse()) + + elifs := branchNodeSpec.GetElseIf() + assert.Equal(t, 1, len(elifs)) + assert.Equal(t, boolExpr, elifs[0].GetCondition()) + assert.Equal(t, &elifNode, elifs[0].GetThenNode()) + + assert.Equal(t, errorMessage, branchNodeSpec.GetElseFail()) + + branchNodeSpec.ElseFail = nil + assert.Nil(t, branchNodeSpec.GetElseFail()) +} diff --git a/flytepropeller/pkg/apis/flyteworkflow/v1alpha1/error_test.go b/flytepropeller/pkg/apis/flyteworkflow/v1alpha1/error_test.go new file mode 100644 index 0000000000..4e0968205d --- /dev/null +++ b/flytepropeller/pkg/apis/flyteworkflow/v1alpha1/error_test.go @@ -0,0 +1,30 @@ +package v1alpha1 + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/flyteorg/flyte/flyteidl/gen/pb-go/flyteidl/core" +) + +func TestExecutionErrorJSONMarshalling(t *testing.T) { + execError := &core.ExecutionError{ + Code: "TestCode", + Message: "Test error message", + ErrorUri: "Test error uri", + } + + execErr := &ExecutionError{ExecutionError: execError} + data, jErr := json.Marshal(execErr) + assert.Nil(t, jErr) + + newExecErr := &ExecutionError{} + uErr := json.Unmarshal(data, newExecErr) + assert.Nil(t, uErr) + + assert.Equal(t, execError.Code, newExecErr.ExecutionError.Code) + assert.Equal(t, execError.Message, newExecErr.ExecutionError.Message) + assert.Equal(t, execError.ErrorUri, newExecErr.ExecutionError.ErrorUri) +} diff --git a/flytepropeller/pkg/apis/flyteworkflow/v1alpha1/iface_test.go b/flytepropeller/pkg/apis/flyteworkflow/v1alpha1/iface_test.go new file mode 100644 index 0000000000..eb2eafa723 --- /dev/null +++ b/flytepropeller/pkg/apis/flyteworkflow/v1alpha1/iface_test.go @@ -0,0 +1,186 @@ +package v1alpha1 + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/flyteorg/flyte/flyteidl/gen/pb-go/flyteidl/core" +) + +func TestNodeKindString(t *testing.T) { + tests := []struct { + kind NodeKind + expected string + }{ + {NodeKindTask, "task"}, + {NodeKindBranch, "branch"}, + {NodeKindWorkflow, "workflow"}, + {NodeKindGate, "gate"}, + {NodeKindArray, "array"}, + {NodeKindStart, "start"}, + {NodeKindEnd, "end"}, + } + + for _, test := range tests { + t.Run(test.expected, func(t *testing.T) { + assert.Equal(t, test.expected, test.kind.String()) + }) + } +} + +func TestNodePhaseString(t *testing.T) { + tests := []struct { + phase NodePhase + expected string + }{ + {NodePhaseNotYetStarted, "NotYetStarted"}, + {NodePhaseQueued, "Queued"}, + {NodePhaseRunning, "Running"}, + {NodePhaseTimingOut, "NodePhaseTimingOut"}, + {NodePhaseTimedOut, "NodePhaseTimedOut"}, + {NodePhaseSucceeding, "Succeeding"}, + {NodePhaseSucceeded, "Succeeded"}, + {NodePhaseFailing, "Failing"}, + {NodePhaseFailed, "Failed"}, + {NodePhaseSkipped, "Skipped"}, + {NodePhaseRetryableFailure, "RetryableFailure"}, + {NodePhaseDynamicRunning, "DynamicRunning"}, + {NodePhaseRecovered, "NodePhaseRecovered"}, + } + + for _, test := range tests { + t.Run(test.expected, func(t *testing.T) { + assert.Equal(t, test.expected, test.phase.String()) + }) + } +} + +func TestWorkflowPhaseString(t *testing.T) { + tests := []struct { + phase WorkflowPhase + expected string + }{ + {WorkflowPhaseReady, "Ready"}, + {WorkflowPhaseRunning, "Running"}, + {WorkflowPhaseSuccess, "Succeeded"}, + {WorkflowPhaseFailed, "Failed"}, + {WorkflowPhaseFailing, "Failing"}, + {WorkflowPhaseSucceeding, "Succeeding"}, + {WorkflowPhaseAborted, "Aborted"}, + {WorkflowPhaseHandlingFailureNode, "HandlingFailureNode"}, + {-1, "Unknown"}, + // Add more cases as needed + } + + for _, test := range tests { + t.Run(test.expected, func(t *testing.T) { + assert.Equal(t, test.expected, test.phase.String()) + }) + } +} + +func TestBranchNodePhaseString(t *testing.T) { + tests := []struct { + phase BranchNodePhase + expected string + }{ + {BranchNodeNotYetEvaluated, "NotYetEvaluated"}, + {BranchNodeSuccess, "BranchEvalSuccess"}, + {BranchNodeError, "BranchEvalFailed"}, + {-1, "Undefined"}, + } + + for _, test := range tests { + t.Run(test.expected, func(t *testing.T) { + assert.Equal(t, test.expected, test.phase.String()) + }) + } +} + +func TestWorkflowOnFailurePolicyStringError(t *testing.T) { + _, err := WorkflowOnFailurePolicyString("NON_EXISTENT_POLICY") + assert.Error(t, err) +} + +func TestWorkflowOnFailurePolicyJSONMarshalling(t *testing.T) { + tests := []struct { + policy WorkflowOnFailurePolicy + jsonStr string + }{ + {WorkflowOnFailurePolicy(core.WorkflowMetadata_FAIL_IMMEDIATELY), `"FAIL_IMMEDIATELY"`}, + {WorkflowOnFailurePolicy(core.WorkflowMetadata_FAIL_AFTER_EXECUTABLE_NODES_COMPLETE), `"FAIL_AFTER_EXECUTABLE_NODES_COMPLETE"`}, + } + + for _, test := range tests { + t.Run(test.jsonStr, func(t *testing.T) { + // Testing marshalling + data, err := json.Marshal(test.policy) + require.NoError(t, err) + assert.Equal(t, test.jsonStr, string(data)) + + // Testing unmarshalling + var unmarshalledPolicy WorkflowOnFailurePolicy + err = json.Unmarshal(data, &unmarshalledPolicy) + require.NoError(t, err) + assert.Equal(t, test.policy, unmarshalledPolicy) + }) + } + + invalidTest := `123` + var policy WorkflowOnFailurePolicy + err := json.Unmarshal([]byte(invalidTest), &policy) + assert.Error(t, err) + assert.Contains(t, err.Error(), "WorkflowOnFailurePolicy should be a string, got 123") + +} + +func TestGetOutputsFile(t *testing.T) { + tests := []struct { + outputDir DataReference + expected DataReference + }{ + {"dir1", "dir1/outputs.pb"}, + {"dir2", "dir2/outputs.pb"}, + } + + for _, tt := range tests { + t.Run(string(tt.outputDir), func(t *testing.T) { // Convert DataReference to string here + assert.Equal(t, tt.expected, GetOutputsFile(tt.outputDir)) + }) + } +} + +func TestGetInputsFile(t *testing.T) { + tests := []struct { + inputDir DataReference + expected DataReference + }{ + {"dir1", "dir1/inputs.pb"}, + {"dir2", "dir2/inputs.pb"}, + } + + for _, tt := range tests { + t.Run(string(tt.inputDir), func(t *testing.T) { + assert.Equal(t, tt.expected, GetInputsFile(tt.inputDir)) + }) + } +} + +func TestGetDeckFile(t *testing.T) { + tests := []struct { + inputDir DataReference + expected DataReference + }{ + {"dir1", "dir1/deck.html"}, + {"dir2", "dir2/deck.html"}, + } + + for _, tt := range tests { + t.Run(string(tt.inputDir), func(t *testing.T) { + assert.Equal(t, tt.expected, GetDeckFile(tt.inputDir)) + }) + } +}