Skip to content

Commit 311f80b

Browse files
committed
tests
1 parent 9eba4b0 commit 311f80b

File tree

1 file changed

+174
-0
lines changed

1 file changed

+174
-0
lines changed

dbos/serialization_test.go

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ package dbos
22

33
import (
44
"context"
5+
"encoding/gob"
56
"errors"
67
"fmt"
8+
"strings"
79
"testing"
810
"time"
911

@@ -44,6 +46,11 @@ type SimpleStruct struct {
4446
B int
4547
}
4648

49+
type PointerResultStruct struct {
50+
Value string
51+
Count int
52+
}
53+
4754
func encodingWorkflowStruct(ctx DBOSContext, input WorkflowInputStruct) (StepOutputStruct, error) {
4855
return RunAsStep(ctx, func(context context.Context) (StepOutputStruct, error) {
4956
return encodingStepStruct(context, StepInputStruct{
@@ -60,12 +67,76 @@ func encodingStepStruct(_ context.Context, input StepInputStruct) (StepOutputStr
6067
}, nil
6168
}
6269

70+
// Test nil pointer is ignored during encode
71+
func encodingWorkflowNilReturn(ctx DBOSContext, shouldReturnNil bool) (string, error) {
72+
pointerResult, err := RunAsStep(ctx, func(context context.Context) (*PointerResultStruct, error) {
73+
if shouldReturnNil {
74+
return nil, nil
75+
}
76+
return &PointerResultStruct{
77+
Value: "pointer result",
78+
Count: 42,
79+
}, nil
80+
})
81+
if err != nil {
82+
return "", fmt.Errorf("pointer step failed: %w", err)
83+
}
84+
// Build result summary
85+
var summary []string
86+
if shouldReturnNil {
87+
summary = append(summary, "All nil types handled successfully")
88+
} else {
89+
if pointerResult != nil {
90+
summary = append(summary, fmt.Sprintf("ptr:%s", pointerResult.Value))
91+
}
92+
}
93+
return strings.Join(summary, ", "), nil
94+
}
95+
96+
// Interface types for testing manual interface registration
97+
type ResponseInterface interface {
98+
GetMessage() string
99+
GetCode() int
100+
}
101+
102+
type ConcreteResponse struct {
103+
Message string
104+
Code int
105+
}
106+
107+
func (c ConcreteResponse) GetMessage() string {
108+
return c.Message
109+
}
110+
111+
func (c ConcreteResponse) GetCode() int {
112+
return c.Code
113+
}
114+
115+
func encodingWorkflowInterface(ctx DBOSContext, input string) (ResponseInterface, error) {
116+
result, err := RunAsStep(ctx, func(context context.Context) (ResponseInterface, error) {
117+
return encodingStepInterface(context, input)
118+
})
119+
if err != nil {
120+
return nil, fmt.Errorf("interface step failed: %w", err)
121+
}
122+
return result, nil
123+
}
124+
125+
func encodingStepInterface(_ context.Context, input string) (ResponseInterface, error) {
126+
return ConcreteResponse{
127+
Message: fmt.Sprintf("Processed: %s", input),
128+
Code: 200,
129+
}, nil
130+
}
131+
63132
func TestWorkflowEncoding(t *testing.T) {
64133
executor := setupDBOS(t, true, true)
65134

66135
// Register workflows with executor
67136
RegisterWorkflow(executor, encodingWorkflowBuiltinTypes)
68137
RegisterWorkflow(executor, encodingWorkflowStruct)
138+
RegisterWorkflow(executor, encodingWorkflowNilReturn)
139+
RegisterWorkflow(executor, encodingWorkflowInterface)
69140

70141
err := Launch(executor)
71142
require.NoError(t, err)
@@ -188,6 +259,109 @@ func TestWorkflowEncoding(t *testing.T) {
188259
assert.Equal(t, "processed by encodingStepStruct", stepOutput.B)
189260
assert.Nil(t, step.Error)
190261
})
262+
263+
t.Run("NilableTypes", func(t *testing.T) {
264+
// Test with non-nil values for all types
265+
directHandle, err := RunWorkflow(executor, encodingWorkflowNilReturn, false)
266+
require.NoError(t, err)
267+
268+
// Test result from direct handle
269+
directResult, err := directHandle.GetResult()
270+
require.NoError(t, err)
271+
require.NotNil(t, directResult)
272+
// Verify that we got results for all types
273+
assert.Contains(t, directResult, "ptr:pointer result")
274+
275+
// Test result from polling handle
276+
retrieveHandler, err := RetrieveWorkflow[string](executor.(*dbosContext), directHandle.GetWorkflowID())
277+
require.NoError(t, err)
278+
retrievedResult, err := retrieveHandler.GetResult()
279+
require.NoError(t, err)
280+
assert.Contains(t, retrievedResult, "ptr:pointer result")
281+
282+
// Test with nil values for all types
283+
nilHandle, err := RunWorkflow(executor, encodingWorkflowNilReturn, true)
284+
require.NoError(t, err)
285+
286+
// Test nil result from direct handle
287+
nilDirectResult, err := nilHandle.GetResult()
288+
require.NoError(t, err)
289+
assert.Equal(t, "All nil types handled successfully", nilDirectResult)
290+
291+
// Test nil result from polling handle
292+
nilRetrieveHandler, err := RetrieveWorkflow[string](executor.(*dbosContext), nilHandle.GetWorkflowID())
293+
require.NoError(t, err)
294+
nilRetrievedResult, err := nilRetrieveHandler.GetResult()
295+
require.NoError(t, err)
296+
assert.Equal(t, "All nil types handled successfully", nilRetrievedResult)
297+
298+
// Test results from GetWorkflowSteps to ensure all steps executed
299+
steps, err := GetWorkflowSteps(executor, directHandle.GetWorkflowID())
300+
require.NoError(t, err)
301+
assert.Equal(t, 1, len(steps), "Expected 1 step for nil-able types")
302+
for _, step := range steps {
303+
assert.Nil(t, step.Error, "No step should have errors")
304+
}
305+
})
306+
307+
t.Run("ManualInterfaceRegistration", func(t *testing.T) {
308+
// Manually register the concrete type for interface testing
309+
gob.Register(ConcreteResponse{})
310+
311+
// Test a workflow that returns an interface with manually registered concrete type
312+
directHandle, err := RunWorkflow(executor, encodingWorkflowInterface, "test-interface")
313+
require.NoError(t, err)
314+
315+
// Test result from direct handle
316+
directResult, err := directHandle.GetResult()
317+
require.NoError(t, err)
318+
require.NotNil(t, directResult)
319+
assert.Equal(t, "Processed: test-interface", directResult.GetMessage())
320+
assert.Equal(t, 200, directResult.GetCode())
321+
322+
// Test result from polling handle
323+
retrieveHandler, err := RetrieveWorkflow[ResponseInterface](executor.(*dbosContext), directHandle.GetWorkflowID())
324+
require.NoError(t, err)
325+
retrievedResult, err := retrieveHandler.GetResult()
326+
require.NoError(t, err)
327+
require.NotNil(t, retrievedResult)
328+
assert.Equal(t, "Processed: test-interface", retrievedResult.GetMessage())
329+
assert.Equal(t, 200, retrievedResult.GetCode())
330+
331+
// Test results from ListWorkflows
332+
workflows, err := ListWorkflows(
333+
executor,
334+
WithWorkflowIDs([]string{directHandle.GetWorkflowID()}),
335+
WithLoadInput(true),
336+
WithLoadOutput(true),
337+
)
338+
require.NoError(t, err)
339+
require.Len(t, workflows, 1)
340+
workflow := workflows[0]
341+
require.NotNil(t, workflow.Input)
342+
workflowInput, ok := workflow.Input.(string)
343+
require.True(t, ok, "expected workflow input to be of type string, got %T", workflow.Input)
344+
assert.Equal(t, "test-interface", workflowInput)
345+
require.NotNil(t, workflow.Output)
346+
// The output should be deserialized as ConcreteResponse since we registered it
347+
workflowOutput, ok := workflow.Output.(ConcreteResponse)
348+
require.True(t, ok, "expected workflow output to be of type ConcreteResponse, got %T", workflow.Output)
349+
assert.Equal(t, "Processed: test-interface", workflowOutput.Message)
350+
assert.Equal(t, 200, workflowOutput.Code)
351+
352+
// Test results from GetWorkflowSteps
353+
steps, err := GetWorkflowSteps(executor, directHandle.GetWorkflowID())
354+
require.NoError(t, err)
355+
require.Len(t, steps, 1)
356+
step := steps[0]
357+
require.NotNil(t, step.Output)
358+
// The step output should also be ConcreteResponse
359+
stepOutput, ok := step.Output.(ConcreteResponse)
360+
require.True(t, ok, "expected step output to be of type ConcreteResponse, got %T", step.Output)
361+
assert.Equal(t, "Processed: test-interface", stepOutput.Message)
362+
assert.Equal(t, 200, stepOutput.Code)
363+
assert.Nil(t, step.Error)
364+
})
191365
}
192366

193367
type UserDefinedEventData struct {

0 commit comments

Comments
 (0)