mirror of
https://github.com/hanzoai/tasks.git
synced 2026-10-04 02:04:03 +00:00
409 lines
13 KiB
Go
409 lines
13 KiB
Go
// The MIT License
|
|
//
|
|
// Copyright (c) 2020 Temporal Technologies Inc. All rights reserved.
|
|
//
|
|
// Copyright (c) 2020 Uber Technologies, Inc.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
// THE SOFTWARE.
|
|
|
|
package matching
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"go.temporal.io/api/serviceerror"
|
|
taskqueuepb "go.temporal.io/api/taskqueue/v1"
|
|
"go.temporal.io/api/workflowservice/v1"
|
|
|
|
persistencepb "go.temporal.io/server/api/persistence/v1"
|
|
)
|
|
|
|
func mkVerIdNode(id string) *taskqueuepb.VersionIdNode {
|
|
return &taskqueuepb.VersionIdNode{
|
|
Version: mkVerId(id),
|
|
}
|
|
}
|
|
|
|
func mkVerId(id string) *taskqueuepb.VersionId {
|
|
return &taskqueuepb.VersionId{
|
|
WorkerBuildId: id,
|
|
}
|
|
}
|
|
|
|
func TestNewDefaultGraphUpdate(t *testing.T) {
|
|
n0 := mkVerIdNode("0")
|
|
n1 := mkVerIdNode("1")
|
|
n1.PreviousIncompatible = n0
|
|
data := &persistencepb.VersioningData{
|
|
CurrentDefault: n1,
|
|
}
|
|
|
|
req := &workflowservice.UpdateWorkerBuildIdOrderingRequest{
|
|
VersionId: mkVerId("2"),
|
|
BecomeDefault: true,
|
|
}
|
|
|
|
err := UpdateVersionsGraph(data, req, 0)
|
|
assert.NoError(t, err)
|
|
|
|
assert.True(t, data.CurrentDefault.Version.Equal(req.VersionId))
|
|
assert.Equal(t, "2", data.CurrentDefault.Version.GetWorkerBuildId())
|
|
assert.Equal(t, n1, data.CurrentDefault.PreviousIncompatible)
|
|
assert.Equal(t, "1", data.CurrentDefault.PreviousIncompatible.Version.GetWorkerBuildId())
|
|
assert.Equal(t, n0, data.CurrentDefault.PreviousIncompatible.PreviousIncompatible)
|
|
assert.Equal(t, "0", data.CurrentDefault.PreviousIncompatible.PreviousIncompatible.Version.GetWorkerBuildId())
|
|
|
|
asResp := ToBuildIdOrderingResponse(data, 0)
|
|
assert.Equal(t, 0, len(asResp.GetCompatibleLeaves()))
|
|
}
|
|
|
|
func TestNewDefaultGraphUpdateOfEmptyGraph(t *testing.T) {
|
|
data := &persistencepb.VersioningData{}
|
|
|
|
req := &workflowservice.UpdateWorkerBuildIdOrderingRequest{
|
|
VersionId: mkVerId("1"),
|
|
BecomeDefault: true,
|
|
}
|
|
|
|
err := UpdateVersionsGraph(data, req, 0)
|
|
assert.NoError(t, err)
|
|
|
|
assert.True(t, data.CurrentDefault.Version.Equal(req.VersionId))
|
|
assert.Equal(t, "1", data.CurrentDefault.Version.GetWorkerBuildId())
|
|
assert.Nil(t, data.CurrentDefault.GetPreviousIncompatible())
|
|
assert.Nil(t, data.CurrentDefault.GetPreviousCompatible())
|
|
}
|
|
|
|
func TestNewDefaultGraphUpdateCompatWithCurDefault(t *testing.T) {
|
|
n0 := mkVerIdNode("0")
|
|
n1 := mkVerIdNode("1")
|
|
n1.PreviousIncompatible = n0
|
|
data := &persistencepb.VersioningData{
|
|
CurrentDefault: n1,
|
|
}
|
|
|
|
req := &workflowservice.UpdateWorkerBuildIdOrderingRequest{
|
|
VersionId: mkVerId("2"),
|
|
PreviousCompatible: mkVerId("1"),
|
|
BecomeDefault: true,
|
|
}
|
|
|
|
err := UpdateVersionsGraph(data, req, 0)
|
|
assert.NoError(t, err)
|
|
|
|
assert.True(t, data.CurrentDefault.Version.Equal(req.VersionId))
|
|
assert.Equal(t, "2", data.CurrentDefault.Version.GetWorkerBuildId())
|
|
assert.Equal(t, n1, data.CurrentDefault.PreviousCompatible)
|
|
assert.Equal(t, "1", data.CurrentDefault.PreviousCompatible.Version.GetWorkerBuildId())
|
|
assert.Equal(t, n0, data.CurrentDefault.PreviousIncompatible)
|
|
assert.Equal(t, "0", data.CurrentDefault.PreviousIncompatible.Version.GetWorkerBuildId())
|
|
}
|
|
|
|
func TestNewDefaultGraphUpdateCompatWithSomethingElse(t *testing.T) {
|
|
n0 := mkVerIdNode("0")
|
|
n1 := mkVerIdNode("1")
|
|
n1.PreviousIncompatible = n0
|
|
data := &persistencepb.VersioningData{
|
|
CurrentDefault: n1,
|
|
}
|
|
|
|
req := &workflowservice.UpdateWorkerBuildIdOrderingRequest{
|
|
VersionId: mkVerId("2"),
|
|
PreviousCompatible: mkVerId("0"),
|
|
BecomeDefault: true,
|
|
}
|
|
|
|
err := UpdateVersionsGraph(data, req, 0)
|
|
assert.Error(t, err)
|
|
assert.IsType(t, &serviceerror.InvalidArgument{}, err)
|
|
}
|
|
|
|
func TestNewCompatibleWithNodeDeepInIncompatChain(t *testing.T) {
|
|
n0 := mkVerIdNode("0")
|
|
n1 := mkVerIdNode("1")
|
|
n1.PreviousIncompatible = n0
|
|
n2 := mkVerIdNode("2")
|
|
n2.PreviousIncompatible = n1
|
|
data := &persistencepb.VersioningData{
|
|
CurrentDefault: n2,
|
|
}
|
|
|
|
req := &workflowservice.UpdateWorkerBuildIdOrderingRequest{
|
|
VersionId: mkVerId("0.1"),
|
|
PreviousCompatible: mkVerId("0"),
|
|
}
|
|
|
|
err := UpdateVersionsGraph(data, req, 0)
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, "2", data.CurrentDefault.Version.GetWorkerBuildId())
|
|
assert.True(t, data.CompatibleLeaves[0].Version.Equal(req.VersionId))
|
|
assert.Equal(t, "0.1", data.CompatibleLeaves[0].Version.GetWorkerBuildId())
|
|
assert.Equal(t, "0", data.CompatibleLeaves[0].PreviousCompatible.Version.GetWorkerBuildId())
|
|
|
|
asResp := ToBuildIdOrderingResponse(data, 0)
|
|
assert.Equal(t, 1, len(asResp.GetCompatibleLeaves()))
|
|
assert.Equal(t, "0.1", asResp.CompatibleLeaves[0].Version.GetWorkerBuildId())
|
|
}
|
|
|
|
func TestNewCompatibleWithNonDefaultGraphUpdate(t *testing.T) {
|
|
n0 := mkVerIdNode("0")
|
|
n1 := mkVerIdNode("1")
|
|
n1.PreviousIncompatible = n0
|
|
data := &persistencepb.VersioningData{
|
|
CurrentDefault: n1,
|
|
}
|
|
|
|
req := &workflowservice.UpdateWorkerBuildIdOrderingRequest{
|
|
VersionId: mkVerId("0.1"),
|
|
PreviousCompatible: mkVerId("0"),
|
|
}
|
|
err := UpdateVersionsGraph(data, req, 0)
|
|
assert.NoError(t, err)
|
|
|
|
assert.True(t, data.CurrentDefault.Version.Equal(n1.Version))
|
|
assert.Equal(t, "1", data.CurrentDefault.Version.GetWorkerBuildId())
|
|
assert.Equal(t, 1, len(data.CompatibleLeaves))
|
|
assert.True(t, data.CompatibleLeaves[0].Version.Equal(req.VersionId))
|
|
assert.Equal(t, "0.1", data.CompatibleLeaves[0].Version.GetWorkerBuildId())
|
|
|
|
req = &workflowservice.UpdateWorkerBuildIdOrderingRequest{
|
|
VersionId: mkVerId("0.2"),
|
|
PreviousCompatible: mkVerId("0.1"),
|
|
}
|
|
err = UpdateVersionsGraph(data, req, 0)
|
|
assert.NoError(t, err)
|
|
|
|
assert.True(t, data.CurrentDefault.Version.Equal(n1.Version))
|
|
assert.Equal(t, "1", data.CurrentDefault.Version.GetWorkerBuildId())
|
|
assert.Equal(t, 1, len(data.CompatibleLeaves))
|
|
assert.True(t, data.CompatibleLeaves[0].Version.Equal(req.VersionId))
|
|
assert.Equal(t, "0.2", data.CompatibleLeaves[0].Version.GetWorkerBuildId())
|
|
|
|
// Ensure setting a compatible version which targets a non-leaf compat version ends up without a branch
|
|
req = &workflowservice.UpdateWorkerBuildIdOrderingRequest{
|
|
VersionId: mkVerId("0.3"),
|
|
PreviousCompatible: mkVerId("0.1"),
|
|
}
|
|
err = UpdateVersionsGraph(data, req, 0)
|
|
assert.NoError(t, err)
|
|
|
|
assert.True(t, data.CurrentDefault.Version.Equal(n1.Version))
|
|
assert.Equal(t, "1", data.CurrentDefault.Version.GetWorkerBuildId())
|
|
assert.Equal(t, 1, len(data.CompatibleLeaves))
|
|
assert.True(t, data.CompatibleLeaves[0].Version.Equal(req.VersionId))
|
|
assert.Equal(t, "0.3", data.CompatibleLeaves[0].Version.GetWorkerBuildId())
|
|
assert.Equal(t, "0.2", data.CompatibleLeaves[0].PreviousCompatible.Version.GetWorkerBuildId())
|
|
}
|
|
|
|
func TestAddingNewNodeCompatWithPreviousWhenNoDefaultNotAllowed(t *testing.T) {
|
|
data := &persistencepb.VersioningData{}
|
|
|
|
req := &workflowservice.UpdateWorkerBuildIdOrderingRequest{
|
|
VersionId: mkVerId("0.1"),
|
|
PreviousCompatible: mkVerId("0"),
|
|
BecomeDefault: true,
|
|
}
|
|
err := UpdateVersionsGraph(data, req, 0)
|
|
assert.Error(t, err)
|
|
assert.IsType(t, &serviceerror.InvalidArgument{}, err)
|
|
}
|
|
|
|
func TestAddingNewNodeWithNoLinksNotAllowed(t *testing.T) {
|
|
data := &persistencepb.VersioningData{}
|
|
|
|
req := &workflowservice.UpdateWorkerBuildIdOrderingRequest{
|
|
VersionId: mkVerId("0.1"),
|
|
}
|
|
err := UpdateVersionsGraph(data, req, 0)
|
|
assert.Error(t, err)
|
|
assert.IsType(t, &serviceerror.InvalidArgument{}, err)
|
|
}
|
|
|
|
func TestUnsetCurrentDefault(t *testing.T) {
|
|
n1 := mkVerIdNode("1")
|
|
data := &persistencepb.VersioningData{
|
|
CurrentDefault: n1,
|
|
}
|
|
|
|
req := &workflowservice.UpdateWorkerBuildIdOrderingRequest{
|
|
VersionId: mkVerId("1"),
|
|
}
|
|
|
|
err := UpdateVersionsGraph(data, req, 0)
|
|
assert.NoError(t, err)
|
|
|
|
assert.Nil(t, data.CurrentDefault)
|
|
}
|
|
|
|
func TestUnsetCurrentDefaultPreviousIncompatBecomesDefault(t *testing.T) {
|
|
n0 := mkVerIdNode("0")
|
|
n1 := mkVerIdNode("1")
|
|
n1.PreviousIncompatible = n0
|
|
data := &persistencepb.VersioningData{
|
|
CurrentDefault: n1,
|
|
}
|
|
|
|
req := &workflowservice.UpdateWorkerBuildIdOrderingRequest{
|
|
VersionId: mkVerId("1"),
|
|
}
|
|
|
|
err := UpdateVersionsGraph(data, req, 0)
|
|
assert.NoError(t, err)
|
|
|
|
assert.True(t, data.CurrentDefault.Version.Equal(n0.Version))
|
|
assert.Equal(t, "0", data.CurrentDefault.Version.GetWorkerBuildId())
|
|
}
|
|
|
|
func TestUnsetCurrentDefaultPreviousCompatBecomesDefault(t *testing.T) {
|
|
n0 := mkVerIdNode("0")
|
|
n1 := mkVerIdNode("1")
|
|
n1d1 := mkVerIdNode("1.1")
|
|
n1.PreviousIncompatible = n0
|
|
n1d1.PreviousCompatible = n1
|
|
data := &persistencepb.VersioningData{
|
|
CurrentDefault: n1d1,
|
|
}
|
|
|
|
req := &workflowservice.UpdateWorkerBuildIdOrderingRequest{
|
|
VersionId: mkVerId("1.1"),
|
|
}
|
|
|
|
err := UpdateVersionsGraph(data, req, 0)
|
|
assert.NoError(t, err)
|
|
|
|
assert.True(t, data.CurrentDefault.Version.Equal(n1.Version))
|
|
assert.Equal(t, "1", data.CurrentDefault.Version.GetWorkerBuildId())
|
|
}
|
|
|
|
func TestDropCompatibleLeaf(t *testing.T) {
|
|
n0 := mkVerIdNode("0")
|
|
n1 := mkVerIdNode("1")
|
|
n1d1 := mkVerIdNode("1.1")
|
|
n1.PreviousIncompatible = n0
|
|
n1d1.PreviousCompatible = n1
|
|
data := &persistencepb.VersioningData{
|
|
CurrentDefault: n1,
|
|
CompatibleLeaves: []*taskqueuepb.VersionIdNode{n1d1},
|
|
}
|
|
|
|
req := &workflowservice.UpdateWorkerBuildIdOrderingRequest{
|
|
VersionId: mkVerId("1.1"),
|
|
}
|
|
|
|
err := UpdateVersionsGraph(data, req, 0)
|
|
assert.NoError(t, err)
|
|
|
|
assert.True(t, data.CurrentDefault.Version.Equal(n1.Version))
|
|
assert.Equal(t, "1", data.CurrentDefault.Version.GetWorkerBuildId())
|
|
assert.Equal(t, 1, len(data.CompatibleLeaves))
|
|
assert.Equal(t, "1", data.CompatibleLeaves[0].Version.GetWorkerBuildId())
|
|
}
|
|
|
|
func TestCompatibleTargetsNotFound(t *testing.T) {
|
|
n0 := mkVerIdNode("0")
|
|
data := &persistencepb.VersioningData{
|
|
CurrentDefault: n0,
|
|
}
|
|
|
|
req := &workflowservice.UpdateWorkerBuildIdOrderingRequest{
|
|
VersionId: mkVerId("1.1"),
|
|
PreviousCompatible: mkVerId("1"),
|
|
}
|
|
|
|
err := UpdateVersionsGraph(data, req, 0)
|
|
assert.Error(t, err)
|
|
assert.IsType(t, &serviceerror.NotFound{}, err)
|
|
}
|
|
|
|
func TestLimitsMaxSize(t *testing.T) {
|
|
data := &persistencepb.VersioningData{}
|
|
maxSize := 1000
|
|
|
|
for i := 0; i < 1024; i++ {
|
|
id := mkVerId(fmt.Sprintf("%d", i))
|
|
req := &workflowservice.UpdateWorkerBuildIdOrderingRequest{
|
|
VersionId: id,
|
|
BecomeDefault: true,
|
|
}
|
|
err := UpdateVersionsGraph(data, req, maxSize)
|
|
assert.NoError(t, err)
|
|
}
|
|
for i := 0; i < 1024; i++ {
|
|
id := mkVerId(fmt.Sprintf("50.%d", i))
|
|
var compatId *taskqueuepb.VersionId
|
|
if i == 0 {
|
|
compatId = mkVerId("50")
|
|
} else {
|
|
compatId = mkVerId(fmt.Sprintf("50.%d", i-1))
|
|
}
|
|
req := &workflowservice.UpdateWorkerBuildIdOrderingRequest{
|
|
VersionId: id,
|
|
PreviousCompatible: compatId,
|
|
}
|
|
err := UpdateVersionsGraph(data, req, maxSize)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
lastNode := data.GetCurrentDefault()
|
|
for {
|
|
if lastNode.GetPreviousIncompatible() == nil {
|
|
break
|
|
}
|
|
lastNode = lastNode.GetPreviousIncompatible()
|
|
}
|
|
assert.Equal(t, mkVerId("24"), lastNode.GetVersion())
|
|
assert.Equal(t, 1, len(data.GetCompatibleLeaves()))
|
|
lastNode = data.GetCompatibleLeaves()[0]
|
|
for {
|
|
if lastNode.GetPreviousCompatible() == nil {
|
|
break
|
|
}
|
|
lastNode = lastNode.GetPreviousCompatible()
|
|
}
|
|
assert.Equal(t, mkVerId("50.24"), lastNode.GetVersion())
|
|
}
|
|
|
|
func FuzzVersionGraphEnsureNoSameTypeDefaults(f *testing.F) {
|
|
f.Fuzz(func(t *testing.T, numUpdates, willPickCompatMod, compatModTarget uint8) {
|
|
addedNodes := make([]*taskqueuepb.VersionId, 0, numUpdates)
|
|
data := &persistencepb.VersioningData{}
|
|
|
|
for i := uint8(0); i < numUpdates; i++ {
|
|
id := mkVerId(fmt.Sprintf("%d", i))
|
|
req := &workflowservice.UpdateWorkerBuildIdOrderingRequest{
|
|
VersionId: id,
|
|
BecomeDefault: true,
|
|
}
|
|
if willPickCompatMod > 0 && compatModTarget > 0 &&
|
|
numUpdates%willPickCompatMod == 0 &&
|
|
uint8(len(addedNodes)) > numUpdates%compatModTarget {
|
|
compatTarget := addedNodes[numUpdates%compatModTarget]
|
|
req.PreviousCompatible = compatTarget
|
|
}
|
|
addedNodes = append(addedNodes, id)
|
|
err := UpdateVersionsGraph(data, req, 0)
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, ToBuildIdOrderingResponse(data, 0))
|
|
}
|
|
})
|
|
}
|