@@ -5,7 +5,7 @@ Test workflow and steps features
55[x] Wrapping various golang methods in DBOS workflows
66[x] workflow idempotency
77[x] workflow DLQ
8- [] workflow conflicting name
8+ [x ] workflow conflicting name
99[] workflow timeouts & deadlines (including child workflows)
1010*/
1111
@@ -1902,6 +1902,153 @@ func getEventIdempotencyWorkflow(ctx DBOSContext, input setEventWorkflowInput) (
19021902 return result , nil
19031903}
19041904
1905+ // Test workflows and steps for parameter mismatch validation
1906+ func conflictWorkflowA (dbosCtx DBOSContext , input string ) (string , error ) {
1907+ return RunAsStep (dbosCtx , func (ctx context.Context ) (string , error ) {
1908+ return conflictStepA (ctx )
1909+ })
1910+ }
1911+
1912+ func conflictWorkflowB (dbosCtx DBOSContext , input string ) (string , error ) {
1913+ return RunAsStep (dbosCtx , func (ctx context.Context ) (string , error ) {
1914+ return conflictStepB (ctx )
1915+ })
1916+ }
1917+
1918+ func conflictStepA (_ context.Context ) (string , error ) {
1919+ return "step-a-result" , nil
1920+ }
1921+
1922+ func conflictStepB (_ context.Context ) (string , error ) {
1923+ return "step-b-result" , nil
1924+ }
1925+
1926+ func workflowWithMultipleSteps (dbosCtx DBOSContext , input string ) (string , error ) {
1927+ // First step
1928+ result1 , err := RunAsStep (dbosCtx , func (ctx context.Context ) (string , error ) {
1929+ return conflictStepA (ctx )
1930+ })
1931+ if err != nil {
1932+ return "" , err
1933+ }
1934+
1935+ // Second step - this is where we'll test step name conflicts
1936+ result2 , err := RunAsStep (dbosCtx , func (ctx context.Context ) (string , error ) {
1937+ return conflictStepB (ctx )
1938+ })
1939+ if err != nil {
1940+ return "" , err
1941+ }
1942+
1943+ return result1 + "-" + result2 , nil
1944+ }
1945+
1946+ func TestWorkflowExecutionMismatch (t * testing.T ) {
1947+ dbosCtx := setupDBOS (t , true , true )
1948+
1949+ // Register workflows for testing
1950+ RegisterWorkflow (dbosCtx , conflictWorkflowA )
1951+ RegisterWorkflow (dbosCtx , conflictWorkflowB )
1952+ RegisterWorkflow (dbosCtx , workflowWithMultipleSteps )
1953+
1954+ t .Run ("WorkflowNameConflict" , func (t * testing.T ) {
1955+ workflowID := uuid .NewString ()
1956+
1957+ // First, run conflictWorkflowA with a specific workflow ID
1958+ handle1 , err := RunAsWorkflow (dbosCtx , conflictWorkflowA , "test-input" , WithWorkflowID (workflowID ))
1959+ if err != nil {
1960+ t .Fatalf ("failed to start first workflow: %v" , err )
1961+ }
1962+
1963+ // Get the result to ensure it completes
1964+ result1 , err := handle1 .GetResult ()
1965+ if err != nil {
1966+ t .Fatalf ("failed to get result from first workflow: %v" , err )
1967+ }
1968+ if result1 != "step-a-result" {
1969+ t .Fatalf ("expected 'step-a-result', got '%s'" , result1 )
1970+ }
1971+
1972+ // Now try to run conflictWorkflowB with the same workflow ID
1973+ // This should return a ConflictingWorkflowError
1974+ _ , err = RunAsWorkflow (dbosCtx , conflictWorkflowB , "test-input" , WithWorkflowID (workflowID ))
1975+ if err == nil {
1976+ t .Fatal ("expected ConflictingWorkflowError when running different workflow with same ID, but got none" )
1977+ }
1978+
1979+ // Check that it's the correct error type
1980+ dbosErr , ok := err .(* DBOSError )
1981+ if ! ok {
1982+ t .Fatalf ("expected error to be of type *DBOSError, got %T" , err )
1983+ }
1984+
1985+ if dbosErr .Code != ConflictingWorkflowError {
1986+ t .Fatalf ("expected error code to be ConflictingWorkflowError, got %v" , dbosErr .Code )
1987+ }
1988+
1989+ // Check that the error message contains the workflow names
1990+ expectedMsgPart := "Workflow already exists with a different name"
1991+ if ! strings .Contains (err .Error (), expectedMsgPart ) {
1992+ t .Fatalf ("expected error message to contain '%s', got '%s'" , expectedMsgPart , err .Error ())
1993+ }
1994+ })
1995+
1996+ t .Run ("StepNameConflict" , func (t * testing.T ) {
1997+ // This test simulates a scenario where a workflow is recovered but
1998+ // the step implementation has changed, causing a step name mismatch
1999+
2000+ // First, start a workflow and let it complete partially
2001+ handle1 , err := RunAsWorkflow (dbosCtx , workflowWithMultipleSteps , "test-input" )
2002+ if err != nil {
2003+ t .Fatalf ("failed to start workflow: %v" , err )
2004+ }
2005+
2006+ // Complete the workflow
2007+ result , err := handle1 .GetResult ()
2008+ if err != nil {
2009+ t .Fatalf ("failed to get result from workflow: %v" , err )
2010+ }
2011+ if result != "step-a-result-step-b-result" {
2012+ t .Fatalf ("expected 'step-a-result-step-b-result', got '%s'" , result )
2013+ }
2014+
2015+ // Now simulate what happens if we try to check operation execution
2016+ // with a different step name for the same step ID
2017+ workflowID := handle1 .GetWorkflowID ()
2018+
2019+ // This directly tests the CheckOperationExecution method with mismatched step name
2020+ // We'll check step ID 0 (first step) but with wrong step name
2021+ wrongStepName := "wrong-step-name"
2022+ _ , err = dbosCtx .(* dbosContext ).systemDB .CheckOperationExecution (dbosCtx , checkOperationExecutionDBInput {
2023+ workflowID : workflowID ,
2024+ stepID : 0 ,
2025+ stepName : wrongStepName ,
2026+ })
2027+
2028+ if err == nil {
2029+ t .Fatal ("expected UnexpectedStep error when checking operation with wrong step name, but got none" )
2030+ }
2031+
2032+ // Check that it's the correct error type
2033+ dbosErr , ok := err .(* DBOSError )
2034+ if ! ok {
2035+ t .Fatalf ("expected error to be of type *DBOSError, got %T" , err )
2036+ }
2037+
2038+ if dbosErr .Code != UnexpectedStep {
2039+ t .Fatalf ("expected error code to be UnexpectedStep, got %v" , dbosErr .Code )
2040+ }
2041+
2042+ // Check that the error message contains step information
2043+ if ! strings .Contains (err .Error (), "Check that your workflow is deterministic" ) {
2044+ t .Fatalf ("expected error message to contain 'Check that your workflow is deterministic', got '%s'" , err .Error ())
2045+ }
2046+ if ! strings .Contains (err .Error (), wrongStepName ) {
2047+ t .Fatalf ("expected error message to contain wrong step name '%s', got '%s'" , wrongStepName , err .Error ())
2048+ }
2049+ })
2050+ }
2051+
19052052func TestSetGetEvent (t * testing.T ) {
19062053 dbosCtx := setupDBOS (t , true , true )
19072054
0 commit comments