From 25f47fa1140c21bfb94b169d08a3af4789d07f68 Mon Sep 17 00:00:00 2001 From: Emma Munley <46881325+EmmaMunley@users.noreply.github.com> Date: Mon, 24 Apr 2023 17:18:17 -0400 Subject: [PATCH] Add Unit Tests for Array Results using [] notation This commit adds test coverage for a pipeline task that emit an array of results and test string replacements from the array of results using indexing. This addresses issue: #6574. --- .../pipelinerun/pipelinerun_test.go | 368 +++++++++++++++++- 1 file changed, 365 insertions(+), 3 deletions(-) diff --git a/pkg/reconciler/pipelinerun/pipelinerun_test.go b/pkg/reconciler/pipelinerun/pipelinerun_test.go index 2cffc61939c..8526fbec8de 100644 --- a/pkg/reconciler/pipelinerun/pipelinerun_test.go +++ b/pkg/reconciler/pipelinerun/pipelinerun_test.go @@ -179,9 +179,25 @@ func getTaskRunByName(t *testing.T, taskRuns map[string]*v1beta1.TaskRun, expect // It will fatal the test if an error occurred. func getTaskRunsForPipelineRun(ctx context.Context, t *testing.T, clients test.Clients, namespace string, prName string) map[string]*v1beta1.TaskRun { t.Helper() + labelSelector := pipeline.PipelineRunLabelKey + "=" + prName + return getTaskRuns(ctx, t, clients, namespace, labelSelector) +} + +// getTaskRunsForPipelineTask returns the set of TaskRuns associated with the input PipelineRun and PipelineTask +// It will fatal the test if an error occurred. +func getTaskRunsForPipelineTask(ctx context.Context, t *testing.T, clients test.Clients, namespace string, prName string, ptLabel string) map[string]*v1beta1.TaskRun { + t.Helper() + labelSelector := pipeline.PipelineRunLabelKey + "=" + prName + "," + pipeline.PipelineTaskLabelKey + "=" + ptLabel + return getTaskRuns(ctx, t, clients, namespace, labelSelector) +} + +// getTaskRuns returns the set of TaskRuns matching the label selector. +// It will fatal the test if an error occurred. +func getTaskRuns(ctx context.Context, t *testing.T, clients test.Clients, namespace string, labelSelector string) map[string]*v1beta1.TaskRun { + t.Helper() opt := metav1.ListOptions{ - LabelSelector: pipeline.PipelineRunLabelKey + "=" + prName, + LabelSelector: labelSelector, } taskRuns, err := clients.Pipeline.TektonV1beta1().TaskRuns(namespace).List(ctx, opt) @@ -202,8 +218,6 @@ func getTaskRunsForPipelineRun(ctx context.Context, t *testing.T, clients test.C // Task that has not been started yet. It verifies that the TaskRun is created, // it checks the resulting API actions, status and events. func TestReconcile(t *testing.T) { - names.TestingSeed() - namespace := "foo" prName := "test-pipeline-run-success" trName := "test-pipeline-run-success-unit-test-1" @@ -9306,6 +9320,354 @@ spec: } } +func TestReconciler_PipelineTaskMatrixResultsWithArrayIndexing(t *testing.T) { + names.TestingSeed() + task := parse.MustParseV1beta1Task(t, ` +metadata: + name: mytask + namespace: foo +spec: + params: + - name: platform + default: mac + steps: + - name: echo + image: alpine + script: | + echo "$(params.platform)" +`) + taskwithresults := parse.MustParseV1beta1Task(t, ` +metadata: + name: taskwithresults + namespace: foo +spec: + results: + - name: platforms + type: array + steps: + - name: produce-a-list-of-platforms + image: bash:latest + script: | + #!/usr/bin/env bash + echo -n "[\"linux\",\"mac\",\"windows\"]" | tee $(results.platforms.path) +`) + + cms := []*corev1.ConfigMap{withEnabledAlphaAPIFields(newFeatureFlagsConfigMap())} + cms = append(cms, withMaxMatrixCombinationsCount(newDefaultsConfigMap(), 10)) + tests := []struct { + name string + pName string + p *v1beta1.Pipeline + tr *v1beta1.TaskRun + expectedTaskRuns []*v1beta1.TaskRun + expectedPipelineRun *v1beta1.PipelineRun + }{{ + name: "indexing results in params", + pName: "p-dag", + p: parse.MustParseV1beta1Pipeline(t, fmt.Sprintf(` +metadata: + name: %s + namespace: foo +spec: + tasks: + - name: pt-with-result + params: + - name: platforms + type: array + taskRef: + name: taskwithresults + - name: echo-platforms + params: + - name: platforms + value: + - $(tasks.pt-with-result.results.platforms[0]) + - $(tasks.pt-with-result.results.platforms[1]) + - $(tasks.pt-with-result.results.platforms[2]) + taskRef: + name: mytask +`, "p-dag")), + tr: mustParseTaskRunWithObjectMeta(t, + taskRunObjectMeta("pr-pt-with-result", "foo", + "pr", "p-dag", "pt-with-result", false), + ` +spec: + serviceAccountName: test-sa + taskRef: + name: taskwithresults +status: + conditions: + - type: Succeeded + status: "True" + reason: Succeeded + message: All Tasks have completed executing + taskResults: + - name: platforms + value: + - linux + - mac + - windows +`), + expectedTaskRuns: []*v1beta1.TaskRun{ + mustParseTaskRunWithObjectMeta(t, + taskRunObjectMeta("pr-echo-platforms", "foo", + "pr", "p-dag", "echo-platforms", false), + ` +spec: + params: + - name: platforms + value: + - linux + - mac + - windows + serviceAccountName: test-sa + taskRef: + name: mytask + kind: Task +labels: + tekton.dev/memberOf: tasks + tekton.dev/pipeline: p-dag +`), + }, + expectedPipelineRun: parse.MustParseV1beta1PipelineRun(t, ` +metadata: + name: pr + namespace: foo + annotations: {} + labels: + tekton.dev/pipeline: p-dag +spec: + serviceAccountName: test-sa + pipelineRef: + name: p-dag +status: + pipelineSpec: + tasks: + - name: pt-with-result + params: + - name: platforms + type: array + taskRef: + name: taskwithresults + kind: Task + - name: echo-platforms + taskRef: + name: mytask + kind: Task + params: + - name: platforms + value: + - $(tasks.pt-with-result.results.platforms[0]) + - $(tasks.pt-with-result.results.platforms[1]) + - $(tasks.pt-with-result.results.platforms[2]) + conditions: + - type: Succeeded + status: "Unknown" + reason: "Running" + message: "Tasks Completed: 1 (Failed: 0, Cancelled 0), Incomplete: 1, Skipped: 0" + childReferences: + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-pt-with-result + pipelineTaskName: pt-with-result + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-echo-platforms + pipelineTaskName: echo-platforms +`), + }, { + name: "indexing results in matrix.params", + pName: "p-dag-2", + p: parse.MustParseV1beta1Pipeline(t, fmt.Sprintf(` +metadata: + name: %s + namespace: foo +spec: + tasks: + - name: pt-with-result + params: + - name: platforms + type: array + taskRef: + name: taskwithresults + - name: echo-platforms + matrix: + params: + - name: platform + value: + - $(tasks.pt-with-result.results.platforms[0]) + - $(tasks.pt-with-result.results.platforms[1]) + - $(tasks.pt-with-result.results.platforms[2]) + taskRef: + name: mytask +`, "p-dag-2")), + tr: mustParseTaskRunWithObjectMeta(t, + taskRunObjectMeta("pr-pt-with-result", "foo", + "pr", "p-dag-2", "pt-with-result", false), + ` +spec: + serviceAccountName: test-sa + taskRef: + name: taskwithresults +status: + conditions: + - type: Succeeded + status: "True" + reason: Succeeded + message: All Tasks have completed executing + taskResults: + - name: platforms + value: + - linux + - mac + - windows +`), + expectedTaskRuns: []*v1beta1.TaskRun{ + mustParseTaskRunWithObjectMeta(t, + taskRunObjectMeta("pr-echo-platforms-0", "foo", + "pr", "p-dag-2", "echo-platforms", false), + ` +spec: + params: + - name: platform + value: linux + serviceAccountName: test-sa + taskRef: + name: mytask + kind: Task +labels: + tekton.dev/memberOf: tasks + tekton.dev/pipeline: p-dag-2 +`), + mustParseTaskRunWithObjectMeta(t, + taskRunObjectMeta("pr-echo-platforms-1", "foo", + "pr", "p-dag-2", "echo-platforms", false), + ` +spec: + params: + - name: platform + value: mac + serviceAccountName: test-sa + taskRef: + name: mytask + kind: Task +labels: + tekton.dev/memberOf: tasks + tekton.dev/pipeline: p-dag-2 +`), + mustParseTaskRunWithObjectMeta(t, + taskRunObjectMeta("pr-echo-platforms-2", "foo", + "pr", "p-dag-2", "echo-platforms", false), + ` +spec: + params: + - name: platform + value: windows + serviceAccountName: test-sa + taskRef: + name: mytask + kind: Task +labels: + tekton.dev/memberOf: tasks + tekton.dev/pipeline: p-dag-2 +`), + }, + expectedPipelineRun: parse.MustParseV1beta1PipelineRun(t, ` +metadata: + name: pr + namespace: foo + annotations: {} + labels: + tekton.dev/pipeline: p-dag-2 +spec: + serviceAccountName: test-sa + pipelineRef: + name: p-dag-2 +status: + pipelineSpec: + tasks: + - name: pt-with-result + params: + - name: platforms + type: array + taskRef: + name: taskwithresults + kind: Task + - name: echo-platforms + taskRef: + name: mytask + kind: Task + matrix: + params: + - name: platform + value: + - $(tasks.pt-with-result.results.platforms[0]) + - $(tasks.pt-with-result.results.platforms[1]) + - $(tasks.pt-with-result.results.platforms[2]) + conditions: + - type: Succeeded + status: "Unknown" + reason: "Running" + message: "Tasks Completed: 1 (Failed: 0, Cancelled 0), Incomplete: 1, Skipped: 0" + childReferences: + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-pt-with-result + pipelineTaskName: pt-with-result + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-echo-platforms-0 + pipelineTaskName: echo-platforms + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-echo-platforms-1 + pipelineTaskName: echo-platforms + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-echo-platforms-2 + pipelineTaskName: echo-platforms +`), + }} + for _, tt := range tests { + t.Run(tt.pName, func(t *testing.T) { + pr := parse.MustParseV1beta1PipelineRun(t, fmt.Sprintf(` +metadata: + name: pr + namespace: foo +spec: + serviceAccountName: test-sa + pipelineRef: + name: %s +`, tt.pName)) + d := test.Data{ + PipelineRuns: []*v1beta1.PipelineRun{pr}, + Pipelines: []*v1beta1.Pipeline{tt.p}, + Tasks: []*v1beta1.Task{task, taskwithresults}, + ConfigMaps: cms, + } + if tt.tr != nil { + d.TaskRuns = []*v1beta1.TaskRun{tt.tr} + } + prt := newPipelineRunTest(t, d) + defer prt.Cancel() + pipelineRun, clients := prt.reconcileRun(pr.Namespace, pr.Name, []string{} /* wantEvents*/, false /* permanentError*/) + + taskRuns := getTaskRunsForPipelineTask(prt.TestAssets.Ctx, t, clients, pr.Namespace, pr.Name, "echo-platforms") + validateTaskRunsCount(t, taskRuns, len(tt.expectedTaskRuns)) + for _, expectedTaskRun := range tt.expectedTaskRuns { + trName := expectedTaskRun.Name + actual := getTaskRunByName(t, taskRuns, trName) + if d := cmp.Diff(expectedTaskRun, actual, ignoreResourceVersion, ignoreTypeMeta); d != "" { + t.Errorf("expected to see TaskRun %v created. Diff %s", expectedTaskRun.Name, diff.PrintWantGot(d)) + } + } + + if d := cmp.Diff(tt.expectedPipelineRun, pipelineRun, ignoreResourceVersion, ignoreTypeMeta, ignoreLastTransitionTime, ignoreStartTime, ignoreFinallyStartTime, cmpopts.EquateEmpty()); d != "" { + t.Errorf("expected PipelineRun was not created. Diff %s", diff.PrintWantGot(d)) + } + }) + } +} + func TestReconciler_PipelineTaskMatrixWithRetries(t *testing.T) { names.TestingSeed()