๐Ÿ“ฆ veggiemonk / workflow

๐Ÿ“„ validation_test.go ยท 177 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177package workflow_test

import (
	"context"
	"testing"

	wf "github.com/veggiemonk/workflow"
)

// TestStepValidation tests the validation functionality
func TestStepValidation(t *testing.T) {
	type TestData struct {
		Value int
	}

	validator := wf.StepValidator[TestData]{}

	t.Run("nil step validation", func(t *testing.T) {
		err := validator.ValidateStep(nil)
		if err == nil {
			t.Error("Expected error for nil step")
		}
	})

	t.Run("valid step validation", func(t *testing.T) {
		step := wf.StepFunc[TestData](func(_ context.Context, data *TestData) (*TestData, error) {
			return data, nil
		})
		err := validator.ValidateStep(step)
		if err != nil {
			t.Errorf("Expected no error for valid step, got %v", err)
		}
	})

	t.Run("pipeline validation", func(t *testing.T) {
		pipeline := wf.NewPipeline[TestData]()
		pipeline.Steps = []wf.Step[TestData]{
			wf.StepFunc[TestData](func(_ context.Context, data *TestData) (*TestData, error) {
				return data, nil
			}),
		}

		err := validator.ValidatePipeline(pipeline)
		if err != nil {
			t.Errorf("Expected no error for valid pipeline, got %v", err)
		}
	})

	t.Run("nil pipeline validation", func(t *testing.T) {
		err := validator.ValidatePipeline(nil)
		if err == nil {
			t.Error("Expected error for nil pipeline")
		}
	})
}

// TestSafeRun tests the safe run functionality
func TestSafeRun(t *testing.T) {
	type TestData struct {
		Value int
	}

	step := wf.StepFunc[TestData](func(_ context.Context, data *TestData) (*TestData, error) {
		data.Value++
		return data, nil
	})

	t.Run("safe run with valid inputs", func(t *testing.T) {
		data := &TestData{Value: 5}
		result, err := wf.SafeRun(context.Background(), step, data)
		if err != nil {
			t.Errorf("Expected no error, got %v", err)
		}
		if result.Value != 6 {
			t.Errorf("Expected value 6, got %d", result.Value)
		}
	})

	t.Run("safe run with nil step", func(t *testing.T) {
		data := &TestData{Value: 5}
		_, err := wf.SafeRun(context.Background(), nil, data)
		if err == nil {
			t.Error("Expected error for nil step")
		}
	})

	t.Run("safe run with nil data", func(t *testing.T) {
		_, err := wf.SafeRun(context.Background(), step, nil)
		if err == nil {
			t.Error("Expected error for nil data")
		}
	})

	t.Run("safe run with nil context", func(t *testing.T) {
		data := &TestData{Value: 5}
		result, err := wf.SafeRun(context.TODO(), step, data)
		if err != nil {
			t.Errorf("Expected no error with nil context, got %v", err)
		}
		if result.Value != 6 {
			t.Errorf("Expected value 6, got %d", result.Value)
		}
	})
}

// TestSafeCopy tests the safe copy functionality
func TestSafeCopy(t *testing.T) {
	type TestData struct {
		Value int
		Slice []int
	}

	t.Run("safe copy with nil", func(t *testing.T) {
		result := wf.SafeCopy[TestData](nil)
		if result != nil {
			t.Error("Expected nil result for nil input")
		}
	})

	t.Run("safe copy with valid data", func(t *testing.T) {
		original := &TestData{
			Value: 42,
			Slice: []int{1, 2, 3},
		}

		cp := wf.SafeCopy(original)
		if cp == nil {
			t.Fatal("Expected non-nil copy")
		}

		// Verify values are copied
		if cp.Value != original.Value {
			t.Errorf("Expected value %d, got %d", original.Value, cp.Value)
		}

		// Verify it's a different instance
		if cp == original {
			t.Error("Expected different instance")
		}

		// Note: This is still a shallow copy for slices
		// The slice itself will be shared between original and copy
	})
}

// TestDeepCopyInterface tests the deep copy interface
func TestDeepCopyInterface(t *testing.T) {
	// Define a type that implements custom copy behavior
	type DeepCopyTestData struct {
		Value int
		Slice []int
	}

	t.Run("shallow copy vs deep copy", func(t *testing.T) {
		original := &DeepCopyTestData{
			Value: 42,
			Slice: []int{1, 2, 3},
		}

		// Test SafeCopy which performs shallow copy
		copied := wf.SafeCopy(original)
		if copied == nil {
			t.Fatal("Expected non-nil copy")
		}

		// Verify values are copied
		if copied.Value != original.Value {
			t.Errorf("Expected value %d, got %d", original.Value, copied.Value)
		}

		// Verify it's a different instance
		if copied == original {
			t.Error("Expected different instance")
		}
	})
}