go.uber.org/cadence@v1.2.9/internal/registry_test.go (about)

     1  // Copyright (c) 2017-2020 Uber Technologies Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package internal
    22  
    23  import (
    24  	"testing"
    25  
    26  	"github.com/stretchr/testify/require"
    27  )
    28  
    29  func TestWorkflowRegistration(t *testing.T) {
    30  	w := &testWorkflowStruct{}
    31  	tests := []struct {
    32  		msg               string
    33  		register          func(r *registry)
    34  		registerPanic     bool
    35  		workflowType      string
    36  		altWorkflowType   string
    37  		resolveByFunction interface{}
    38  		resolveByAlias    string
    39  	}{
    40  		{
    41  			msg:               "register workflow function",
    42  			register:          func(r *registry) { r.RegisterWorkflow(testWorkflowFunction) },
    43  			workflowType:      "go.uber.org/cadence/internal.testWorkflowFunction",
    44  			resolveByFunction: testWorkflowFunction,
    45  		},
    46  		{
    47  			msg: "register workflow function with short name",
    48  			register: func(r *registry) {
    49  				r.RegisterWorkflowWithOptions(testWorkflowFunction, RegisterWorkflowOptions{EnableShortName: true})
    50  			},
    51  			workflowType:      "testWorkflowFunction",
    52  			resolveByFunction: testWorkflowFunction,
    53  		},
    54  		{
    55  			msg: "register workflow function with alias",
    56  			register: func(r *registry) {
    57  				r.RegisterWorkflowWithOptions(testWorkflowFunction, RegisterWorkflowOptions{Name: "workflow.alias"})
    58  			},
    59  			workflowType:      "workflow.alias",
    60  			resolveByFunction: testWorkflowFunction,
    61  			resolveByAlias:    "workflow.alias",
    62  		},
    63  		{
    64  			msg:               "register workflow struct function (backwards compatible)",
    65  			register:          func(r *registry) { r.RegisterWorkflow(w.Method) },
    66  			workflowType:      "go.uber.org/cadence/internal.(*testWorkflowStruct).Method",
    67  			altWorkflowType:   "go.uber.org/cadence/internal.(*testWorkflowStruct).Method-fm",
    68  			resolveByFunction: w.Method,
    69  		},
    70  		{
    71  			msg: "register duplicated workflow in one registry (should panic)",
    72  			register: func(r *registry) {
    73  				r.RegisterWorkflow(testWorkflowFunction)
    74  				r.RegisterWorkflow(testWorkflowFunction)
    75  			},
    76  			registerPanic: true,
    77  		},
    78  		{
    79  			msg: "register duplicated workflow with already registered check disabled",
    80  			register: func(r *registry) {
    81  				r.RegisterWorkflow(testWorkflowFunction)
    82  				r.RegisterWorkflowWithOptions(testWorkflowFunction, RegisterWorkflowOptions{DisableAlreadyRegisteredCheck: true})
    83  			},
    84  			workflowType:      "go.uber.org/cadence/internal.testWorkflowFunction",
    85  			resolveByFunction: testWorkflowFunction,
    86  		},
    87  		{
    88  			msg: "register duplicated workflow in chained registry (should panic)",
    89  			register: func(r *registry) {
    90  				r.next.RegisterWorkflow(testWorkflowFunction)
    91  				r.RegisterWorkflow(testWorkflowFunction)
    92  			},
    93  			registerPanic: true,
    94  		},
    95  	}
    96  
    97  	for _, tt := range tests {
    98  		t.Run(tt.msg, func(t *testing.T) {
    99  			r := newRegistry()
   100  			if tt.registerPanic {
   101  				require.Panics(t, func() { tt.register(r) }, "register should panic")
   102  				return
   103  			}
   104  
   105  			tt.register(r)
   106  
   107  			// Verify registered workflow type
   108  			workflowType := r.GetRegisteredWorkflowTypes()[0]
   109  			require.Equal(t, tt.workflowType, workflowType)
   110  
   111  			// Verify workflow is resolved from workflow type
   112  			_, ok := r.getWorkflowFn(tt.workflowType)
   113  			require.True(t, ok)
   114  
   115  			// Verify workflow is resolved from alternative (backwards compatible) workflow type
   116  			if len(tt.altWorkflowType) > 0 {
   117  				_, ok = r.getWorkflowFn(tt.altWorkflowType)
   118  				require.True(t, ok)
   119  			}
   120  
   121  			// Verify resolving by function reference
   122  			workflowType = getWorkflowFunctionName(r, tt.resolveByFunction)
   123  			require.Equal(t, tt.workflowType, workflowType)
   124  
   125  			// Verify resolving by alias
   126  			if tt.resolveByAlias != "" {
   127  				workflowType = getWorkflowFunctionName(r, tt.resolveByAlias)
   128  				require.Equal(t, tt.workflowType, workflowType)
   129  			}
   130  		})
   131  	}
   132  }
   133  
   134  func TestActivityRegistration(t *testing.T) {
   135  	tests := []struct {
   136  		msg               string
   137  		register          func(r *registry)
   138  		registerPanic     bool
   139  		activityType      string
   140  		altActivityType   string
   141  		resolveByFunction interface{}
   142  		resolveByAlias    string
   143  	}{
   144  		{
   145  			msg:               "register activity function",
   146  			register:          func(r *registry) { r.RegisterActivity(testActivityFunction) },
   147  			activityType:      "go.uber.org/cadence/internal.testActivityFunction",
   148  			resolveByFunction: testActivityFunction,
   149  		},
   150  		{
   151  			msg: "register activity function with short name",
   152  			register: func(r *registry) {
   153  				r.RegisterActivityWithOptions(testActivityFunction, RegisterActivityOptions{EnableShortName: true})
   154  			},
   155  			activityType:      "testActivityFunction",
   156  			resolveByFunction: testActivityFunction,
   157  		},
   158  		{
   159  			msg: "register activity function with an alias",
   160  			register: func(r *registry) {
   161  				r.RegisterActivityWithOptions(testActivityFunction, RegisterActivityOptions{Name: "activity.alias"})
   162  			},
   163  			activityType:      "activity.alias",
   164  			resolveByFunction: testActivityFunction,
   165  			resolveByAlias:    "activity.alias",
   166  		},
   167  		{
   168  			msg:               "register activity struct",
   169  			register:          func(r *registry) { r.RegisterActivity(&testActivityStruct{}) },
   170  			activityType:      "go.uber.org/cadence/internal.(*testActivityStruct).Method",
   171  			altActivityType:   "go.uber.org/cadence/internal.(*testActivityStruct).Method-fm",
   172  			resolveByFunction: (&testActivityStruct{}).Method,
   173  		},
   174  		{
   175  			msg: "register activity struct with short name",
   176  			register: func(r *registry) {
   177  				r.RegisterActivityWithOptions(&testActivityStruct{}, RegisterActivityOptions{EnableShortName: true})
   178  			},
   179  			activityType:      "Method",
   180  			resolveByFunction: (&testActivityStruct{}).Method,
   181  		},
   182  		{
   183  			msg: "register activity struct with a prefix",
   184  			register: func(r *registry) {
   185  				r.RegisterActivityWithOptions(&testActivityStruct{}, RegisterActivityOptions{Name: "prefix."})
   186  			},
   187  			activityType:      "prefix.Method",
   188  			resolveByFunction: (&testActivityStruct{}).Method,
   189  			resolveByAlias:    "prefix.Method",
   190  		},
   191  		{
   192  			msg: "register duplicated activity function in one registry (should panic)",
   193  			register: func(r *registry) {
   194  				duplicatedActivityAlias := "activity.alias"
   195  				r.RegisterActivityWithOptions(testActivityFunction, RegisterActivityOptions{Name: duplicatedActivityAlias})
   196  				r.RegisterActivityWithOptions(testActivityFunction, RegisterActivityOptions{Name: duplicatedActivityAlias})
   197  			},
   198  			registerPanic: true,
   199  		},
   200  		{
   201  			msg: "register duplicated activity struct with already registered check disabled",
   202  			register: func(r *registry) {
   203  				r.RegisterActivity(&testActivityStruct{})
   204  				r.RegisterActivityWithOptions(&testActivityStruct{}, RegisterActivityOptions{DisableAlreadyRegisteredCheck: true})
   205  			},
   206  			activityType:      "go.uber.org/cadence/internal.(*testActivityStruct).Method",
   207  			resolveByFunction: (&testActivityStruct{}).Method,
   208  		},
   209  		{
   210  			msg: "register duplicated activity function in chained registry (should panic)",
   211  			register: func(r *registry) {
   212  				r.next.RegisterActivity(testActivityFunction)
   213  				r.RegisterActivity(testActivityFunction)
   214  			},
   215  			registerPanic: true,
   216  		},
   217  	}
   218  	for _, tt := range tests {
   219  		t.Run(tt.msg, func(t *testing.T) {
   220  			r := newRegistry()
   221  			if tt.registerPanic {
   222  				require.Panics(t, func() { tt.register(r) }, "register should panic")
   223  				return
   224  			}
   225  
   226  			tt.register(r)
   227  
   228  			// Verify registered activity type
   229  			activityType := r.getRegisteredActivities()[0].ActivityType().Name
   230  			require.Equal(t, tt.activityType, activityType, "activity type")
   231  
   232  			// Verify activity is resolved from activity type
   233  			_, ok := r.GetActivity(tt.activityType)
   234  			require.True(t, ok)
   235  
   236  			// Verify activity is resolved from alternative (backwards compatible) activity type
   237  			if len(tt.altActivityType) > 0 {
   238  				_, ok = r.GetActivity(tt.altActivityType)
   239  				require.True(t, ok)
   240  			}
   241  
   242  			// Verify resolving by function reference
   243  			activityType = getActivityFunctionName(r, tt.resolveByFunction)
   244  			require.Equal(t, tt.activityType, activityType, "resolve by function reference")
   245  
   246  			// Verify resolving by alias
   247  			if tt.resolveByAlias != "" {
   248  				activityType = getActivityFunctionName(r, tt.resolveByAlias)
   249  				require.Equal(t, tt.activityType, activityType, "resolve by alias")
   250  			}
   251  		})
   252  	}
   253  }
   254  
   255  type testWorkflowStruct struct{}
   256  type testActivityStruct struct{}
   257  
   258  func (ts *testWorkflowStruct) Method(ctx Context) error { return nil }
   259  func (ts *testActivityStruct) Method() error            { return nil }
   260  
   261  func testActivityFunction() error            { return nil }
   262  func testWorkflowFunction(ctx Context) error { return nil }