go.temporal.io/server@v1.23.0/common/persistence/tests/visibility_persistence_suite.go (about)

     1  // The MIT License
     2  //
     3  // Copyright (c) 2020 Temporal Technologies Inc.  All rights reserved.
     4  //
     5  // Copyright (c) 2020 Uber Technologies, Inc.
     6  //
     7  // Permission is hereby granted, free of charge, to any person obtaining a copy
     8  // of this software and associated documentation files (the "Software"), to deal
     9  // in the Software without restriction, including without limitation the rights
    10  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    11  // copies of the Software, and to permit persons to whom the Software is
    12  // furnished to do so, subject to the following conditions:
    13  //
    14  // The above copyright notice and this permission notice shall be included in
    15  // all copies or substantial portions of the Software.
    16  //
    17  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    18  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    19  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    20  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    21  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    22  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    23  // THE SOFTWARE.
    24  
    25  package tests
    26  
    27  import (
    28  	"context"
    29  	"fmt"
    30  	"time"
    31  
    32  	"github.com/golang/mock/gomock"
    33  	"github.com/pborman/uuid"
    34  	"github.com/stretchr/testify/require"
    35  	commonpb "go.temporal.io/api/common/v1"
    36  	enumspb "go.temporal.io/api/enums/v1"
    37  	workflowpb "go.temporal.io/api/workflow/v1"
    38  	"go.temporal.io/api/workflowservice/v1"
    39  
    40  	"go.temporal.io/server/common/debug"
    41  	"go.temporal.io/server/common/dynamicconfig"
    42  	"go.temporal.io/server/common/log/tag"
    43  	"go.temporal.io/server/common/metrics"
    44  	"go.temporal.io/server/common/namespace"
    45  	"go.temporal.io/server/common/payload"
    46  	"go.temporal.io/server/common/persistence"
    47  	persistencetests "go.temporal.io/server/common/persistence/persistence-tests"
    48  	"go.temporal.io/server/common/persistence/sql/sqlplugin/mysql"
    49  	"go.temporal.io/server/common/persistence/sql/sqlplugin/postgresql"
    50  	"go.temporal.io/server/common/persistence/visibility"
    51  	"go.temporal.io/server/common/persistence/visibility/manager"
    52  	"go.temporal.io/server/common/persistence/visibility/store/standard/cassandra"
    53  	"go.temporal.io/server/common/primitives/timestamp"
    54  	"go.temporal.io/server/common/resolver"
    55  	"go.temporal.io/server/common/searchattribute"
    56  )
    57  
    58  type (
    59  	// VisibilityPersistenceSuite tests visibility persistence
    60  	VisibilityPersistenceSuite struct {
    61  		// override suite.Suite.Assertions with require.Assertions; this means that s.NotNil(nil) will stop the test,
    62  		// not merely log an error
    63  		*require.Assertions
    64  		controller *gomock.Controller
    65  
    66  		*persistencetests.TestBase
    67  		VisibilityMgr                  manager.VisibilityManager
    68  		SearchAttributesProvider       searchattribute.Provider
    69  		SearchAttributesMapperProvider searchattribute.MapperProvider
    70  		CustomVisibilityStoreFactory   visibility.VisibilityStoreFactory
    71  
    72  		ctx    context.Context
    73  		cancel context.CancelFunc
    74  	}
    75  )
    76  
    77  // SetupSuite implementation
    78  func (s *VisibilityPersistenceSuite) SetupSuite() {
    79  	s.DefaultTestCluster.SetupTestDatabase()
    80  	cfg := s.DefaultTestCluster.Config()
    81  
    82  	var err error
    83  	s.controller = gomock.NewController(s.T())
    84  	s.SearchAttributesProvider = searchattribute.NewTestProvider()
    85  	s.SearchAttributesMapperProvider = searchattribute.NewTestMapperProvider(nil)
    86  	s.VisibilityMgr, err = visibility.NewManager(
    87  		cfg,
    88  		resolver.NewNoopResolver(),
    89  		s.CustomVisibilityStoreFactory,
    90  		nil,
    91  		nil,
    92  		s.SearchAttributesProvider,
    93  		s.SearchAttributesMapperProvider,
    94  		dynamicconfig.GetIntPropertyFn(1000),
    95  		dynamicconfig.GetIntPropertyFn(1000),
    96  		dynamicconfig.GetFloatPropertyFn(0.2),
    97  		dynamicconfig.GetBoolPropertyFnFilteredByNamespace(false),
    98  		dynamicconfig.GetStringPropertyFn(visibility.SecondaryVisibilityWritingModeOff),
    99  		dynamicconfig.GetBoolPropertyFnFilteredByNamespace(false),
   100  		dynamicconfig.GetBoolPropertyFnFilteredByNamespace(true),
   101  		metrics.NoopMetricsHandler,
   102  		s.Logger,
   103  	)
   104  
   105  	if err != nil {
   106  		// s.NoError doesn't work here.
   107  		s.Logger.Fatal("Unable to create visibility manager", tag.Error(err))
   108  	}
   109  }
   110  
   111  // SetupTest implementation
   112  func (s *VisibilityPersistenceSuite) SetupTest() {
   113  	// Have to define our overridden assertions in the test setup. If we did it earlier, s.T() will return nil
   114  	s.Assertions = require.New(s.T())
   115  	s.ctx, s.cancel = context.WithTimeout(context.Background(), 30*time.Second*debug.TimeoutMultiplier)
   116  }
   117  
   118  func (s *VisibilityPersistenceSuite) TearDownTest() {
   119  	s.cancel()
   120  }
   121  
   122  // TearDownSuite implementation
   123  func (s *VisibilityPersistenceSuite) TearDownSuite() {
   124  	s.VisibilityMgr.Close()
   125  	s.DefaultTestCluster.TearDownTestDatabase()
   126  }
   127  
   128  // TestBasicVisibility test
   129  func (s *VisibilityPersistenceSuite) TestBasicVisibility() {
   130  	testNamespaceUUID := namespace.ID(uuid.New())
   131  	startTime := time.Now().UTC().Add(time.Second * -5)
   132  	startReq := s.createOpenWorkflowRecord(testNamespaceUUID, "visibility-workflow-test", "visibility-workflow", startTime, "test-queue")
   133  
   134  	resp, err1 := s.VisibilityMgr.ListOpenWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequest{
   135  		NamespaceID:       testNamespaceUUID,
   136  		PageSize:          1,
   137  		EarliestStartTime: startTime,
   138  		LatestStartTime:   startTime,
   139  	})
   140  	s.Nil(err1)
   141  	s.Equal(1, len(resp.Executions))
   142  	s.assertOpenExecutionEquals(startReq, resp.Executions[0])
   143  
   144  	closeReq := s.createClosedWorkflowRecord(startReq, time.Now())
   145  
   146  	resp, err3 := s.VisibilityMgr.ListOpenWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequest{
   147  		NamespaceID:       testNamespaceUUID,
   148  		PageSize:          1,
   149  		EarliestStartTime: startTime,
   150  		LatestStartTime:   startTime,
   151  	})
   152  	s.Nil(err3)
   153  	s.Equal(0, len(resp.Executions))
   154  
   155  	resp, err4 := s.VisibilityMgr.ListClosedWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequest{
   156  		NamespaceID:       testNamespaceUUID,
   157  		PageSize:          1,
   158  		EarliestStartTime: startTime,
   159  		LatestStartTime:   time.Now(),
   160  	})
   161  	s.Nil(err4)
   162  	s.Equal(1, len(resp.Executions))
   163  	s.assertClosedExecutionEquals(closeReq, resp.Executions[0])
   164  }
   165  
   166  // TestBasicVisibilityTimeSkew test
   167  func (s *VisibilityPersistenceSuite) TestBasicVisibilityTimeSkew() {
   168  	testNamespaceUUID := namespace.ID(uuid.New())
   169  
   170  	startTime := time.Now()
   171  	openRecord := s.createOpenWorkflowRecord(testNamespaceUUID, "visibility-workflow-test-time-skew", "visibility-workflow", startTime, "test-queue")
   172  
   173  	resp, err1 := s.VisibilityMgr.ListOpenWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequest{
   174  		NamespaceID:       testNamespaceUUID,
   175  		PageSize:          1,
   176  		EarliestStartTime: startTime,
   177  		LatestStartTime:   startTime,
   178  	})
   179  	s.NoError(err1)
   180  	s.Equal(1, len(resp.Executions))
   181  	s.assertOpenExecutionEquals(openRecord, resp.Executions[0])
   182  
   183  	closedRecord := s.createClosedWorkflowRecord(openRecord, startTime.Add(-10*time.Millisecond))
   184  
   185  	resp, err3 := s.VisibilityMgr.ListOpenWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequest{
   186  		NamespaceID:       testNamespaceUUID,
   187  		PageSize:          1,
   188  		EarliestStartTime: startTime,
   189  		LatestStartTime:   startTime,
   190  	})
   191  	s.NoError(err3)
   192  	s.Equal(0, len(resp.Executions))
   193  
   194  	resp, err4 := s.VisibilityMgr.ListClosedWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequest{
   195  		NamespaceID:       testNamespaceUUID,
   196  		PageSize:          1,
   197  		EarliestStartTime: startTime.Add(-10 * time.Millisecond), // This is actually close_time
   198  		LatestStartTime:   startTime.Add(-10 * time.Millisecond),
   199  	})
   200  	s.NoError(err4)
   201  	s.Equal(1, len(resp.Executions))
   202  	s.assertClosedExecutionEquals(closedRecord, resp.Executions[0])
   203  }
   204  
   205  func (s *VisibilityPersistenceSuite) TestBasicVisibilityShortWorkflow() {
   206  	testNamespaceUUID := namespace.ID(uuid.New())
   207  
   208  	startTime := time.Now().UTC()
   209  	openRecord := s.createOpenWorkflowRecord(testNamespaceUUID, "visibility-workflow-test-short-workflow", "visibility-workflow", startTime, "test-queue")
   210  	closedRecord := s.createClosedWorkflowRecord(openRecord, startTime.Add(10*time.Millisecond))
   211  
   212  	resp, err3 := s.VisibilityMgr.ListOpenWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequest{
   213  		NamespaceID:       testNamespaceUUID,
   214  		PageSize:          1,
   215  		EarliestStartTime: startTime,
   216  		LatestStartTime:   startTime,
   217  	})
   218  	s.NoError(err3)
   219  	s.Equal(0, len(resp.Executions))
   220  
   221  	resp, err4 := s.VisibilityMgr.ListClosedWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequest{
   222  		NamespaceID:       testNamespaceUUID,
   223  		PageSize:          1,
   224  		EarliestStartTime: startTime.Add(10 * time.Millisecond), // This is actually close_time
   225  		LatestStartTime:   startTime.Add(10 * time.Millisecond),
   226  	})
   227  	s.NoError(err4)
   228  	s.Equal(1, len(resp.Executions))
   229  	s.assertClosedExecutionEquals(closedRecord, resp.Executions[0])
   230  }
   231  
   232  // TestVisibilityPagination test
   233  func (s *VisibilityPersistenceSuite) TestVisibilityPagination() {
   234  	testNamespaceUUID := namespace.ID(uuid.New())
   235  
   236  	// Create 2 executions
   237  	startTime1 := time.Now().UTC()
   238  	openRecord1 := s.createOpenWorkflowRecord(testNamespaceUUID, "visibility-pagination-test1", "visibility-workflow", startTime1, "test-queue")
   239  
   240  	startTime2 := startTime1.Add(time.Second)
   241  	openRecord2 := s.createOpenWorkflowRecord(testNamespaceUUID, "visibility-pagination-test2", "visibility-workflow", startTime2, "test-queue")
   242  
   243  	// Get the first one
   244  	resp, err2 := s.VisibilityMgr.ListOpenWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequest{
   245  		NamespaceID:       testNamespaceUUID,
   246  		PageSize:          1,
   247  		EarliestStartTime: startTime1,
   248  		LatestStartTime:   startTime2,
   249  	})
   250  	s.Nil(err2)
   251  	s.Equal(1, len(resp.Executions))
   252  	s.assertOpenExecutionEquals(openRecord2, resp.Executions[0])
   253  
   254  	// Use token to get the second one
   255  	resp, err3 := s.VisibilityMgr.ListOpenWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequest{
   256  		NamespaceID:       testNamespaceUUID,
   257  		PageSize:          1,
   258  		EarliestStartTime: startTime1,
   259  		LatestStartTime:   startTime2,
   260  		NextPageToken:     resp.NextPageToken,
   261  	})
   262  	s.Nil(err3)
   263  	s.Equal(1, len(resp.Executions))
   264  	s.assertOpenExecutionEquals(openRecord1, resp.Executions[0])
   265  
   266  	// It is possible to not return non empty token which is going to return empty result
   267  	if len(resp.NextPageToken) != 0 {
   268  		// Now should get empty result by using token
   269  		resp, err4 := s.VisibilityMgr.ListOpenWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequest{
   270  			NamespaceID:       testNamespaceUUID,
   271  			PageSize:          1,
   272  			EarliestStartTime: startTime1,
   273  			LatestStartTime:   startTime2,
   274  			NextPageToken:     resp.NextPageToken,
   275  		})
   276  		s.Nil(err4)
   277  		s.Equal(0, len(resp.Executions))
   278  	}
   279  }
   280  
   281  // TestFilteringByStartTime test
   282  func (s *VisibilityPersistenceSuite) TestFilteringByStartTime() {
   283  	testNamespaceUUID := namespace.ID(uuid.New())
   284  	startTime := time.Now()
   285  
   286  	// Create 2 open workflows, one started 2hrs ago, the other started just now.
   287  	openRecord1 := s.createOpenWorkflowRecord(testNamespaceUUID, "visibility-filtering-test1", "visibility-workflow-1", startTime.Add(-2*time.Hour), "test-queue")
   288  	openRecord2 := s.createOpenWorkflowRecord(testNamespaceUUID, "visibility-filtering-test2", "visibility-workflow-2", startTime, "test-queue")
   289  
   290  	// List open workflows with start time filter
   291  	resp, err := s.VisibilityMgr.ListOpenWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequest{
   292  		NamespaceID:       testNamespaceUUID,
   293  		PageSize:          2,
   294  		EarliestStartTime: time.Now().Add(-time.Hour),
   295  		LatestStartTime:   time.Now(),
   296  	})
   297  	s.NoError(err)
   298  	s.Equal(1, len(resp.Executions))
   299  	s.assertOpenExecutionEquals(openRecord2, resp.Executions[0])
   300  
   301  	// List with WorkflowType filter in query string
   302  	queryStr := fmt.Sprintf(`StartTime BETWEEN "%v" AND "%v"`, time.Now().Add(-time.Hour).Format(time.RFC3339Nano), time.Now().Format(time.RFC3339Nano))
   303  	resp, err = s.VisibilityMgr.ListWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequestV2{
   304  		NamespaceID: testNamespaceUUID,
   305  		PageSize:    2,
   306  		Query:       queryStr,
   307  	})
   308  	s.Nil(err)
   309  	s.Equal(1, len(resp.Executions))
   310  	s.assertOpenExecutionEquals(openRecord2, resp.Executions[0])
   311  
   312  	queryStr = fmt.Sprintf(`StartTime BETWEEN "%v" AND "%v"`, time.Now().Add(-3*time.Hour).Format(time.RFC3339Nano), time.Now().Format(time.RFC3339Nano))
   313  	resp, err = s.VisibilityMgr.ListWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequestV2{
   314  		NamespaceID: testNamespaceUUID,
   315  		PageSize:    2,
   316  		Query:       queryStr,
   317  	})
   318  	s.Nil(err)
   319  	s.Equal(2, len(resp.Executions))
   320  
   321  	resp, err = s.VisibilityMgr.ListWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequestV2{
   322  		NamespaceID: testNamespaceUUID,
   323  		PageSize:    2,
   324  		Query:       queryStr + ` AND WorkflowType = "visibility-workflow-1"`,
   325  	})
   326  	s.Nil(err)
   327  	s.Equal(1, len(resp.Executions))
   328  	s.assertOpenExecutionEquals(openRecord1, resp.Executions[0])
   329  }
   330  
   331  // TestFilteringByType test
   332  func (s *VisibilityPersistenceSuite) TestFilteringByType() {
   333  	testNamespaceUUID := namespace.ID(uuid.New())
   334  	startTime := time.Now()
   335  
   336  	// Create 2 executions
   337  	openRecord1 := s.createOpenWorkflowRecord(testNamespaceUUID, "visibility-filtering-test1", "visibility-workflow-1", startTime, "test-queue")
   338  	openRecord2 := s.createOpenWorkflowRecord(testNamespaceUUID, "visibility-filtering-test2", "visibility-workflow-2", startTime, "test-queue")
   339  
   340  	// List open with filtering
   341  	resp, err2 := s.VisibilityMgr.ListOpenWorkflowExecutionsByType(s.ctx, &manager.ListWorkflowExecutionsByTypeRequest{
   342  		ListWorkflowExecutionsRequest: &manager.ListWorkflowExecutionsRequest{
   343  			NamespaceID:       testNamespaceUUID,
   344  			PageSize:          2,
   345  			EarliestStartTime: startTime,
   346  			LatestStartTime:   startTime,
   347  		},
   348  		WorkflowTypeName: "visibility-workflow-1",
   349  	})
   350  	s.Nil(err2)
   351  	s.Equal(1, len(resp.Executions))
   352  	s.assertOpenExecutionEquals(openRecord1, resp.Executions[0])
   353  
   354  	// List with WorkflowType filter in query string
   355  	resp, err := s.VisibilityMgr.ListWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequestV2{
   356  		NamespaceID: testNamespaceUUID,
   357  		PageSize:    2,
   358  		Query:       `WorkflowType = "visibility-workflow-1"`,
   359  	})
   360  	s.Nil(err)
   361  	s.Equal(1, len(resp.Executions))
   362  	s.assertOpenExecutionEquals(openRecord1, resp.Executions[0])
   363  
   364  	// Close both executions
   365  	s.createClosedWorkflowRecord(openRecord1, time.Now())
   366  	closedRecord2 := s.createClosedWorkflowRecord(openRecord2, time.Now())
   367  
   368  	// List closed with filtering
   369  	resp, err5 := s.VisibilityMgr.ListClosedWorkflowExecutionsByType(s.ctx, &manager.ListWorkflowExecutionsByTypeRequest{
   370  		ListWorkflowExecutionsRequest: &manager.ListWorkflowExecutionsRequest{
   371  			NamespaceID:       testNamespaceUUID,
   372  			PageSize:          2,
   373  			EarliestStartTime: startTime,
   374  			LatestStartTime:   time.Now(),
   375  		},
   376  		WorkflowTypeName: "visibility-workflow-2",
   377  	})
   378  	s.Nil(err5)
   379  	s.Equal(1, len(resp.Executions))
   380  	s.assertClosedExecutionEquals(closedRecord2, resp.Executions[0])
   381  
   382  	// List with WorkflowType filter in query string
   383  	resp, err = s.VisibilityMgr.ListWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequestV2{
   384  		NamespaceID: testNamespaceUUID,
   385  		PageSize:    2,
   386  		Query:       `WorkflowType = "visibility-workflow-2"`,
   387  	})
   388  	s.Nil(err)
   389  	s.Equal(1, len(resp.Executions))
   390  	s.assertClosedExecutionEquals(closedRecord2, resp.Executions[0])
   391  }
   392  
   393  // TestFilteringByWorkflowID test
   394  func (s *VisibilityPersistenceSuite) TestFilteringByWorkflowID() {
   395  	testNamespaceUUID := namespace.ID(uuid.New())
   396  	startTime := time.Now()
   397  
   398  	// Create 2 executions
   399  	openRecord1 := s.createOpenWorkflowRecord(testNamespaceUUID, "visibility-filtering-test1", "visibility-workflow", startTime, "test-queue")
   400  	openRecord2 := s.createOpenWorkflowRecord(testNamespaceUUID, "visibility-filtering-test2", "visibility-workflow", startTime, "test-queue")
   401  
   402  	// List open with filtering
   403  	resp, err2 := s.VisibilityMgr.ListOpenWorkflowExecutionsByWorkflowID(s.ctx, &manager.ListWorkflowExecutionsByWorkflowIDRequest{
   404  		ListWorkflowExecutionsRequest: &manager.ListWorkflowExecutionsRequest{
   405  			NamespaceID:       testNamespaceUUID,
   406  			PageSize:          2,
   407  			EarliestStartTime: startTime,
   408  			LatestStartTime:   startTime,
   409  		},
   410  		WorkflowID: "visibility-filtering-test1",
   411  	})
   412  	s.Nil(err2)
   413  	s.Equal(1, len(resp.Executions))
   414  	s.assertOpenExecutionEquals(openRecord1, resp.Executions[0])
   415  
   416  	// List workflow with workflowID filter in query string
   417  	resp, err := s.VisibilityMgr.ListWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequestV2{
   418  		NamespaceID: testNamespaceUUID,
   419  		PageSize:    2,
   420  		Query:       `WorkflowId = "visibility-filtering-test1"`,
   421  	})
   422  	s.Nil(err)
   423  	s.Equal(1, len(resp.Executions))
   424  	s.assertOpenExecutionEquals(openRecord1, resp.Executions[0])
   425  
   426  	// Close both executions
   427  	s.createClosedWorkflowRecord(openRecord1, time.Now())
   428  	closedRecord2 := s.createClosedWorkflowRecord(openRecord2, time.Now())
   429  
   430  	// List closed with filtering
   431  	resp, err5 := s.VisibilityMgr.ListClosedWorkflowExecutionsByWorkflowID(s.ctx, &manager.ListWorkflowExecutionsByWorkflowIDRequest{
   432  		ListWorkflowExecutionsRequest: &manager.ListWorkflowExecutionsRequest{
   433  			NamespaceID:       testNamespaceUUID,
   434  			PageSize:          2,
   435  			EarliestStartTime: startTime,
   436  			LatestStartTime:   time.Now(),
   437  		},
   438  		WorkflowID: "visibility-filtering-test2",
   439  	})
   440  	s.Nil(err5)
   441  	s.Equal(1, len(resp.Executions))
   442  	s.assertClosedExecutionEquals(closedRecord2, resp.Executions[0])
   443  
   444  	// List workflow with workflowID filter in query string
   445  	resp, err = s.VisibilityMgr.ListWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequestV2{
   446  		NamespaceID: testNamespaceUUID,
   447  		PageSize:    2,
   448  		Query:       `WorkflowId = "visibility-filtering-test2"`,
   449  	})
   450  	s.Nil(err)
   451  	s.Equal(1, len(resp.Executions))
   452  	s.assertClosedExecutionEquals(closedRecord2, resp.Executions[0])
   453  }
   454  
   455  // TestFilteringByStatus test
   456  func (s *VisibilityPersistenceSuite) TestFilteringByStatus() {
   457  	testNamespaceUUID := namespace.ID(uuid.New())
   458  	startTime := time.Now()
   459  
   460  	// Create 2 executions
   461  	workflowExecution1 := commonpb.WorkflowExecution{
   462  		WorkflowId: "visibility-filtering-test1",
   463  		RunId:      "fb15e4b5-356f-466d-8c6d-a29223e5c536",
   464  	}
   465  	err0 := s.VisibilityMgr.RecordWorkflowExecutionStarted(s.ctx, &manager.RecordWorkflowExecutionStartedRequest{
   466  		VisibilityRequestBase: &manager.VisibilityRequestBase{
   467  			NamespaceID:      testNamespaceUUID,
   468  			Execution:        &workflowExecution1,
   469  			WorkflowTypeName: "visibility-workflow",
   470  			StartTime:        startTime,
   471  			Status:           enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING,
   472  		},
   473  	})
   474  	s.Nil(err0)
   475  
   476  	workflowExecution2 := commonpb.WorkflowExecution{
   477  		WorkflowId: "visibility-filtering-test2",
   478  		RunId:      "843f6fc7-102a-4c63-a2d4-7c653b01bf52",
   479  	}
   480  	err1 := s.VisibilityMgr.RecordWorkflowExecutionStarted(s.ctx, &manager.RecordWorkflowExecutionStartedRequest{
   481  		VisibilityRequestBase: &manager.VisibilityRequestBase{
   482  			NamespaceID:      testNamespaceUUID,
   483  			Execution:        &workflowExecution2,
   484  			WorkflowTypeName: "visibility-workflow",
   485  			StartTime:        startTime,
   486  			Status:           enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING,
   487  		},
   488  	})
   489  	s.Nil(err1)
   490  
   491  	// Close both executions with different status
   492  	err2 := s.VisibilityMgr.RecordWorkflowExecutionClosed(s.ctx, &manager.RecordWorkflowExecutionClosedRequest{
   493  		VisibilityRequestBase: &manager.VisibilityRequestBase{
   494  			NamespaceID:      testNamespaceUUID,
   495  			Execution:        &workflowExecution1,
   496  			WorkflowTypeName: "visibility-workflow",
   497  			StartTime:        startTime,
   498  			Status:           enumspb.WORKFLOW_EXECUTION_STATUS_COMPLETED,
   499  		},
   500  		CloseTime: time.Now(),
   501  	})
   502  	s.Nil(err2)
   503  
   504  	closeReq := &manager.RecordWorkflowExecutionClosedRequest{
   505  		VisibilityRequestBase: &manager.VisibilityRequestBase{
   506  			NamespaceID:      testNamespaceUUID,
   507  			Execution:        &workflowExecution2,
   508  			WorkflowTypeName: "visibility-workflow",
   509  			StartTime:        startTime,
   510  			Status:           enumspb.WORKFLOW_EXECUTION_STATUS_FAILED,
   511  		},
   512  		CloseTime:     time.Now(),
   513  		HistoryLength: 3,
   514  	}
   515  	err3 := s.VisibilityMgr.RecordWorkflowExecutionClosed(s.ctx, closeReq)
   516  	s.Nil(err3)
   517  
   518  	// List closed with filtering
   519  	resp, err4 := s.VisibilityMgr.ListClosedWorkflowExecutionsByStatus(s.ctx, &manager.ListClosedWorkflowExecutionsByStatusRequest{
   520  		ListWorkflowExecutionsRequest: &manager.ListWorkflowExecutionsRequest{
   521  			NamespaceID:       testNamespaceUUID,
   522  			PageSize:          2,
   523  			EarliestStartTime: startTime,
   524  			LatestStartTime:   time.Now(),
   525  		},
   526  		Status: enumspb.WORKFLOW_EXECUTION_STATUS_FAILED,
   527  	})
   528  	s.Nil(err4)
   529  	s.Equal(1, len(resp.Executions))
   530  	s.assertClosedExecutionEquals(closeReq, resp.Executions[0])
   531  
   532  	resp, err := s.VisibilityMgr.ListWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequestV2{
   533  		NamespaceID: testNamespaceUUID,
   534  		PageSize:    5,
   535  		Query:       `ExecutionStatus = "Failed"`,
   536  	})
   537  	s.Nil(err)
   538  	s.Equal(1, len(resp.Executions))
   539  	s.assertClosedExecutionEquals(closeReq, resp.Executions[0])
   540  }
   541  
   542  // TestDelete test
   543  func (s *VisibilityPersistenceSuite) TestDeleteWorkflow() {
   544  	openRows := 10
   545  	closedRows := 5
   546  	testNamespaceUUID := namespace.ID(uuid.New())
   547  	closeTime := time.Now().UTC()
   548  	startTime := closeTime.Add(-5 * time.Second)
   549  	var pendingExecutions []*commonpb.WorkflowExecution
   550  	for i := 0; i < openRows; i++ {
   551  		workflowExecution := commonpb.WorkflowExecution{
   552  			WorkflowId: uuid.New(),
   553  			RunId:      uuid.New(),
   554  		}
   555  		pendingExecutions = append(pendingExecutions, &workflowExecution)
   556  		err0 := s.VisibilityMgr.RecordWorkflowExecutionStarted(s.ctx, &manager.RecordWorkflowExecutionStartedRequest{
   557  			VisibilityRequestBase: &manager.VisibilityRequestBase{
   558  				NamespaceID:      testNamespaceUUID,
   559  				Execution:        &workflowExecution,
   560  				WorkflowTypeName: "visibility-workflow",
   561  				StartTime:        startTime,
   562  				Status:           enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING,
   563  			},
   564  		})
   565  		s.Nil(err0)
   566  	}
   567  
   568  	for i := 0; i < closedRows; i++ {
   569  		closeReq := &manager.RecordWorkflowExecutionClosedRequest{
   570  			VisibilityRequestBase: &manager.VisibilityRequestBase{
   571  				NamespaceID:      testNamespaceUUID,
   572  				Execution:        pendingExecutions[i],
   573  				WorkflowTypeName: "visibility-workflow",
   574  				StartTime:        startTime,
   575  				Status:           enumspb.WORKFLOW_EXECUTION_STATUS_FAILED,
   576  			},
   577  			CloseTime:     closeTime,
   578  			HistoryLength: 3,
   579  		}
   580  		err1 := s.VisibilityMgr.RecordWorkflowExecutionClosed(s.ctx, closeReq)
   581  		s.Nil(err1)
   582  	}
   583  
   584  	resp, err3 := s.VisibilityMgr.ListClosedWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequest{
   585  		NamespaceID:       testNamespaceUUID,
   586  		EarliestStartTime: startTime,
   587  		LatestStartTime:   closeTime,
   588  		PageSize:          10,
   589  	})
   590  	s.Nil(err3)
   591  	s.Equal(closedRows, len(resp.Executions))
   592  
   593  	// Delete closed workflow
   594  	for _, row := range resp.Executions {
   595  		err4 := s.VisibilityMgr.DeleteWorkflowExecution(s.ctx, &manager.VisibilityDeleteWorkflowExecutionRequest{
   596  			NamespaceID: testNamespaceUUID,
   597  			WorkflowID:  row.GetExecution().GetWorkflowId(),
   598  			RunID:       row.GetExecution().GetRunId(),
   599  			CloseTime:   closeTime,
   600  		})
   601  		s.Nil(err4)
   602  	}
   603  	resp, err5 := s.VisibilityMgr.ListClosedWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequest{
   604  		NamespaceID:       testNamespaceUUID,
   605  		EarliestStartTime: startTime,
   606  		LatestStartTime:   closeTime,
   607  		PageSize:          10,
   608  	})
   609  	s.Nil(err5)
   610  	s.Equal(0, len(resp.Executions))
   611  
   612  	resp, err6 := s.VisibilityMgr.ListOpenWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequest{
   613  		NamespaceID:       testNamespaceUUID,
   614  		EarliestStartTime: startTime,
   615  		LatestStartTime:   closeTime,
   616  		PageSize:          10,
   617  	})
   618  	s.Nil(err6)
   619  	s.Equal(openRows-closedRows, len(resp.Executions))
   620  	// Delete open workflow
   621  	for _, row := range resp.Executions {
   622  		err7 := s.VisibilityMgr.DeleteWorkflowExecution(s.ctx, &manager.VisibilityDeleteWorkflowExecutionRequest{
   623  			NamespaceID: testNamespaceUUID,
   624  			WorkflowID:  row.GetExecution().GetWorkflowId(),
   625  			RunID:       row.GetExecution().GetRunId(),
   626  			StartTime:   startTime,
   627  		})
   628  		s.Nil(err7)
   629  	}
   630  	resp, err8 := s.VisibilityMgr.ListOpenWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequest{
   631  		NamespaceID:       testNamespaceUUID,
   632  		EarliestStartTime: startTime,
   633  		LatestStartTime:   closeTime,
   634  		PageSize:          10,
   635  	})
   636  	s.Nil(err8)
   637  	s.Equal(0, len(resp.Executions))
   638  }
   639  
   640  // TestUpsertWorkflowExecution test
   641  func (s *VisibilityPersistenceSuite) TestUpsertWorkflowExecution() {
   642  	temporalChangeVersionPayload, _ := payload.Encode([]string{"dummy"})
   643  	tests := []struct {
   644  		request  *manager.UpsertWorkflowExecutionRequest
   645  		expected error
   646  	}{
   647  		{
   648  			request: &manager.UpsertWorkflowExecutionRequest{
   649  				VisibilityRequestBase: &manager.VisibilityRequestBase{
   650  					NamespaceID:      "",
   651  					Namespace:        "",
   652  					Execution:        &commonpb.WorkflowExecution{},
   653  					WorkflowTypeName: "",
   654  					StartTime:        time.Time{},
   655  					ExecutionTime:    time.Time{},
   656  					TaskID:           0,
   657  					Memo:             nil,
   658  					SearchAttributes: &commonpb.SearchAttributes{
   659  						IndexedFields: map[string]*commonpb.Payload{
   660  							searchattribute.TemporalChangeVersion: temporalChangeVersionPayload,
   661  						},
   662  					},
   663  					Status: enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING,
   664  				},
   665  			},
   666  			expected: nil,
   667  		},
   668  		{
   669  			request: &manager.UpsertWorkflowExecutionRequest{
   670  				VisibilityRequestBase: &manager.VisibilityRequestBase{
   671  					NamespaceID:      "",
   672  					Namespace:        "",
   673  					Execution:        &commonpb.WorkflowExecution{},
   674  					WorkflowTypeName: "",
   675  					StartTime:        time.Time{},
   676  					ExecutionTime:    time.Time{},
   677  					TaskID:           0,
   678  					Memo:             nil,
   679  					SearchAttributes: nil,
   680  					Status:           enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING,
   681  				},
   682  			},
   683  			// To avoid blocking the task queue processors on non-ElasticSearch visibility stores
   684  			// we simply treat any attempts to perform Upserts as "no-ops"
   685  			// Attempts to Scan, Count or List will still fail for non-ES stores.
   686  			expected: nil,
   687  		},
   688  	}
   689  
   690  	for _, test := range tests {
   691  		s.Equal(test.expected, s.VisibilityMgr.UpsertWorkflowExecution(s.ctx, test.request))
   692  	}
   693  }
   694  
   695  // TestGetWorkflowExecution test
   696  func (s *VisibilityPersistenceSuite) TestGetWorkflowExecution() {
   697  	testNamespaceUUID := namespace.ID(uuid.New())
   698  	closeTime := time.Now().UTC()
   699  	startTime := closeTime.Add(-5 * time.Second)
   700  
   701  	var startRequests []*manager.RecordWorkflowExecutionStartedRequest
   702  	for i := 0; i < 5; i++ {
   703  		startRequests = append(
   704  			startRequests,
   705  			s.createOpenWorkflowRecord(
   706  				testNamespaceUUID,
   707  				"visibility-workflow-test",
   708  				"visibility-workflow",
   709  				startTime,
   710  				"test-queue",
   711  			),
   712  		)
   713  	}
   714  	for _, req := range startRequests {
   715  		resp, err := s.VisibilityMgr.GetWorkflowExecution(
   716  			s.ctx,
   717  			&manager.GetWorkflowExecutionRequest{
   718  				NamespaceID: testNamespaceUUID,
   719  				RunID:       req.Execution.RunId,
   720  				StartTime:   startTime,
   721  			},
   722  		)
   723  		s.NoError(err)
   724  		s.assertOpenExecutionEquals(req, resp.Execution)
   725  	}
   726  
   727  	var closeRequests []*manager.RecordWorkflowExecutionClosedRequest
   728  	for _, startReq := range startRequests {
   729  		closeRequests = append(closeRequests, s.createClosedWorkflowRecord(startReq, closeTime))
   730  	}
   731  	for _, req := range closeRequests {
   732  		resp, err := s.VisibilityMgr.GetWorkflowExecution(
   733  			s.ctx,
   734  			&manager.GetWorkflowExecutionRequest{
   735  				NamespaceID: testNamespaceUUID,
   736  				RunID:       req.Execution.RunId,
   737  				CloseTime:   closeTime,
   738  			},
   739  		)
   740  		s.NoError(err)
   741  		s.assertClosedExecutionEquals(req, resp.Execution)
   742  	}
   743  }
   744  
   745  // TestAdvancedVisibilityPagination test
   746  func (s *VisibilityPersistenceSuite) TestAdvancedVisibilityPagination() {
   747  	testNamespaceUUID := namespace.ID(uuid.New())
   748  
   749  	// Generate 5 workflow records, keep 2 open and 3 closed.
   750  	var startReqs []*manager.RecordWorkflowExecutionStartedRequest
   751  	var closeReqs []*manager.RecordWorkflowExecutionClosedRequest
   752  	for i := 0; i < 5; i++ {
   753  		startReq := s.createOpenWorkflowRecord(testNamespaceUUID, fmt.Sprintf("advanced-visibility-%v", i), "visibility-workflow", time.Now(), "test-queue")
   754  		if i <= 1 {
   755  			startReqs = append([]*manager.RecordWorkflowExecutionStartedRequest{startReq}, startReqs...)
   756  		} else {
   757  			closeReq := s.createClosedWorkflowRecord(startReq, time.Now())
   758  			closeReqs = append([]*manager.RecordWorkflowExecutionClosedRequest{closeReq}, closeReqs...)
   759  		}
   760  	}
   761  
   762  	for pageSize := 1; pageSize <= 5; pageSize++ {
   763  		executions := make(map[string]*workflowpb.WorkflowExecutionInfo)
   764  		for _, e := range s.listWithPagination(testNamespaceUUID, 5) {
   765  			executions[e.GetExecution().GetWorkflowId()] = e
   766  		}
   767  
   768  		// there is no order guarantee from the list method, so we have to find the right execution
   769  		for _, r := range startReqs {
   770  			id := r.Execution.GetWorkflowId()
   771  			e, ok := executions[id]
   772  			s.True(ok)
   773  			s.assertOpenExecutionEquals(r, e)
   774  			delete(executions, id)
   775  		}
   776  		for _, r := range closeReqs {
   777  			id := r.Execution.GetWorkflowId()
   778  			e, ok := executions[id]
   779  			s.True(ok)
   780  			s.assertClosedExecutionEquals(r, e)
   781  			delete(executions, id)
   782  		}
   783  		s.Empty(executions, "Unexpected executions returned from list method")
   784  	}
   785  }
   786  
   787  func (s *VisibilityPersistenceSuite) TestCountWorkflowExecutions() {
   788  	switch s.VisibilityMgr.GetStoreNames()[0] {
   789  	case mysql.PluginName, postgresql.PluginName, postgresql.PluginNamePGX, cassandra.CassandraPersistenceName:
   790  		s.T().Skip("Not supported by standard visibility")
   791  	}
   792  
   793  	testNamespaceUUID := namespace.ID(uuid.New())
   794  	closeTime := time.Now().UTC()
   795  	startTime := closeTime.Add(-5 * time.Second)
   796  
   797  	for i := 0; i < 5; i++ {
   798  		s.createOpenWorkflowRecord(
   799  			testNamespaceUUID,
   800  			"visibility-workflow-test",
   801  			"visibility-workflow",
   802  			startTime,
   803  			"test-queue",
   804  		)
   805  	}
   806  
   807  	resp, err := s.VisibilityMgr.CountWorkflowExecutions(
   808  		s.ctx,
   809  		&manager.CountWorkflowExecutionsRequest{
   810  			NamespaceID: testNamespaceUUID,
   811  			Query:       "",
   812  		},
   813  	)
   814  	s.NoError(err)
   815  	s.Equal(int64(5), resp.Count)
   816  	s.Nil(resp.Groups)
   817  }
   818  
   819  func (s *VisibilityPersistenceSuite) TestCountGroupByWorkflowExecutions() {
   820  	switch s.VisibilityMgr.GetStoreNames()[0] {
   821  	case mysql.PluginName, postgresql.PluginName, postgresql.PluginNamePGX, cassandra.CassandraPersistenceName:
   822  		s.T().Skip("Not supported by standard visibility")
   823  	}
   824  
   825  	testNamespaceUUID := namespace.ID(uuid.New())
   826  	closeTime := time.Now().UTC()
   827  	startTime := closeTime.Add(-5 * time.Second)
   828  
   829  	var startRequests []*manager.RecordWorkflowExecutionStartedRequest
   830  	for i := 0; i < 5; i++ {
   831  		startRequests = append(
   832  			startRequests,
   833  			s.createOpenWorkflowRecord(
   834  				testNamespaceUUID,
   835  				"visibility-workflow-test",
   836  				"visibility-workflow",
   837  				startTime,
   838  				"test-queue",
   839  			),
   840  		)
   841  	}
   842  
   843  	runningStatusPayload, _ := searchattribute.EncodeValue(
   844  		enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING.String(),
   845  		enumspb.INDEXED_VALUE_TYPE_KEYWORD,
   846  	)
   847  	resp, err := s.VisibilityMgr.CountWorkflowExecutions(
   848  		s.ctx,
   849  		&manager.CountWorkflowExecutionsRequest{
   850  			NamespaceID: testNamespaceUUID,
   851  			Query:       "GROUP BY ExecutionStatus",
   852  		},
   853  	)
   854  	s.NoError(err)
   855  	s.Equal(int64(5), resp.Count)
   856  	s.Equal(
   857  		[]*workflowservice.CountWorkflowExecutionsResponse_AggregationGroup{
   858  			{
   859  				GroupValues: []*commonpb.Payload{runningStatusPayload},
   860  				Count:       int64(5),
   861  			},
   862  		},
   863  		resp.Groups,
   864  	)
   865  
   866  	for i := 0; i < 2; i++ {
   867  		s.createClosedWorkflowRecord(startRequests[i], closeTime)
   868  	}
   869  
   870  	resp, err = s.VisibilityMgr.CountWorkflowExecutions(
   871  		s.ctx,
   872  		&manager.CountWorkflowExecutionsRequest{
   873  			NamespaceID: testNamespaceUUID,
   874  			Query:       "GROUP BY ExecutionStatus",
   875  		},
   876  	)
   877  	s.NoError(err)
   878  	s.Equal(int64(5), resp.Count)
   879  }
   880  
   881  func (s *VisibilityPersistenceSuite) listWithPagination(namespaceID namespace.ID, pageSize int) []*workflowpb.WorkflowExecutionInfo {
   882  	var executions []*workflowpb.WorkflowExecutionInfo
   883  	resp, err := s.VisibilityMgr.ListWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequestV2{
   884  		NamespaceID: namespaceID,
   885  		PageSize:    pageSize,
   886  		Query:       "",
   887  	})
   888  	s.Nil(err)
   889  	executions = append(executions, resp.Executions...)
   890  
   891  	for len(resp.NextPageToken) > 0 {
   892  		resp, err = s.VisibilityMgr.ListWorkflowExecutions(s.ctx, &manager.ListWorkflowExecutionsRequestV2{
   893  			NamespaceID:   namespaceID,
   894  			PageSize:      pageSize,
   895  			Query:         "",
   896  			NextPageToken: resp.NextPageToken,
   897  		})
   898  		s.Nil(err)
   899  		executions = append(executions, resp.Executions...)
   900  	}
   901  
   902  	return executions
   903  }
   904  
   905  func (s *VisibilityPersistenceSuite) createClosedWorkflowRecord(
   906  	startReq *manager.RecordWorkflowExecutionStartedRequest,
   907  	closeTime time.Time,
   908  ) *manager.RecordWorkflowExecutionClosedRequest {
   909  	closeReq := &manager.RecordWorkflowExecutionClosedRequest{
   910  		VisibilityRequestBase: &manager.VisibilityRequestBase{
   911  			NamespaceID:      startReq.NamespaceID,
   912  			Execution:        startReq.Execution,
   913  			WorkflowTypeName: startReq.WorkflowTypeName,
   914  			StartTime:        startReq.StartTime,
   915  			Status:           enumspb.WORKFLOW_EXECUTION_STATUS_COMPLETED,
   916  		},
   917  		CloseTime:     closeTime,
   918  		HistoryLength: 5,
   919  	}
   920  	err := s.VisibilityMgr.RecordWorkflowExecutionClosed(s.ctx, closeReq)
   921  	s.Nil(err)
   922  	return closeReq
   923  }
   924  
   925  func (s *VisibilityPersistenceSuite) createOpenWorkflowRecord(
   926  	namespaceID namespace.ID,
   927  	workflowID string,
   928  	workflowType string,
   929  	startTime time.Time,
   930  	taskQueue string,
   931  ) *manager.RecordWorkflowExecutionStartedRequest {
   932  	workflowExecution := commonpb.WorkflowExecution{
   933  		WorkflowId: workflowID,
   934  		RunId:      uuid.New(),
   935  	}
   936  	startReq := &manager.RecordWorkflowExecutionStartedRequest{
   937  		VisibilityRequestBase: &manager.VisibilityRequestBase{
   938  			NamespaceID:      namespaceID,
   939  			Execution:        &workflowExecution,
   940  			WorkflowTypeName: workflowType,
   941  			StartTime:        startTime,
   942  			Status:           enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING,
   943  			TaskQueue:        taskQueue,
   944  		},
   945  	}
   946  	err := s.VisibilityMgr.RecordWorkflowExecutionStarted(s.ctx, startReq)
   947  	s.Nil(err)
   948  	return startReq
   949  }
   950  
   951  func (s *VisibilityPersistenceSuite) assertClosedExecutionEquals(
   952  	req *manager.RecordWorkflowExecutionClosedRequest, resp *workflowpb.WorkflowExecutionInfo) {
   953  	s.Equal(req.Execution.RunId, resp.Execution.RunId)
   954  	s.Equal(req.Execution.WorkflowId, resp.Execution.WorkflowId)
   955  	s.Equal(req.WorkflowTypeName, resp.GetType().GetName())
   956  	s.Equal(persistence.UnixMilliseconds(req.StartTime), persistence.UnixMilliseconds(timestamp.TimeValue(resp.GetStartTime())))
   957  	s.Equal(persistence.UnixMilliseconds(req.CloseTime), persistence.UnixMilliseconds(timestamp.TimeValue(resp.GetCloseTime())))
   958  	s.Equal(req.Status, resp.GetStatus())
   959  	s.Equal(req.HistoryLength, resp.HistoryLength)
   960  }
   961  
   962  func (s *VisibilityPersistenceSuite) assertOpenExecutionEquals(
   963  	req *manager.RecordWorkflowExecutionStartedRequest, resp *workflowpb.WorkflowExecutionInfo) {
   964  	s.Equal(req.Execution.GetRunId(), resp.Execution.GetRunId())
   965  	s.Equal(req.Execution.WorkflowId, resp.Execution.WorkflowId)
   966  	s.Equal(req.WorkflowTypeName, resp.GetType().GetName())
   967  	s.Equal(persistence.UnixMilliseconds(req.StartTime), persistence.UnixMilliseconds(timestamp.TimeValue(resp.GetStartTime())))
   968  	s.Nil(resp.CloseTime)
   969  	s.Equal(resp.Status, enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING)
   970  	s.Zero(resp.HistoryLength)
   971  }