diff --git a/cmd/client/command/helper.go b/cmd/client/command/helper.go index 1d395ac1..ade4f35c 100644 --- a/cmd/client/command/helper.go +++ b/cmd/client/command/helper.go @@ -51,7 +51,7 @@ func printCluster(cluster *store.Cluster) { role = strings.ToUpper(store.RoleMaster) } migratingStatus := "NO" - if shard.MigratingSlot != nil { + if shard.IsMigrating() { migratingStatus = fmt.Sprintf("%s --> %d", shard.MigratingSlot, shard.TargetShardIndex) } columns := []string{fmt.Sprintf("%d", i), node.ID(), node.Addr(), role, migratingStatus} diff --git a/controller/cluster.go b/controller/cluster.go index 2d6802e6..2cb08b5c 100755 --- a/controller/cluster.go +++ b/controller/cluster.go @@ -318,19 +318,12 @@ func (c *ClusterChecker) tryUpdateMigrationStatus(ctx context.Context, clonedClu if !shard.IsMigrating() { continue } - sourceNodeClusterInfo, err := shard.GetMasterNode().GetClusterInfo(ctx) if err != nil { log.Error("Failed to get the cluster info from the source node", zap.Error(err)) return } - if sourceNodeClusterInfo.MigratingSlot == nil { - log.Error("The source migration slot is empty", - zap.String("migrating_slot", shard.MigratingSlot.String()), - ) - return - } - if !sourceNodeClusterInfo.MigratingSlot.Equal(shard.MigratingSlot) { + if !sourceNodeClusterInfo.MigratingSlot.Equal(shard.MigratingSlot.SlotRange) { log.Error("Mismatch migrating slot", zap.String("source_migrating_slot", sourceNodeClusterInfo.MigratingSlot.String()), zap.String("migrating_slot", shard.MigratingSlot.String()), @@ -355,9 +348,9 @@ func (c *ClusterChecker) tryUpdateMigrationStatus(ctx context.Context, clonedClu c.updateCluster(clonedCluster) log.Warn("Failed to migrate the slot", zap.String("slot", migratingSlot.String())) case "success": - clonedCluster.Shards[i].SlotRanges = store.RemoveSlotFromSlotRanges(clonedCluster.Shards[i].SlotRanges, *shard.MigratingSlot) + clonedCluster.Shards[i].SlotRanges = store.RemoveSlotFromSlotRanges(clonedCluster.Shards[i].SlotRanges, shard.MigratingSlot.SlotRange) clonedCluster.Shards[shard.TargetShardIndex].SlotRanges = store.AddSlotToSlotRanges( - clonedCluster.Shards[shard.TargetShardIndex].SlotRanges, *shard.MigratingSlot, + clonedCluster.Shards[shard.TargetShardIndex].SlotRanges, shard.MigratingSlot.SlotRange, ) migratedSlot := shard.MigratingSlot clonedCluster.Shards[i].ClearMigrateState() diff --git a/controller/cluster_test.go b/controller/cluster_test.go index d415f3f3..a1a720a6 100644 --- a/controller/cluster_test.go +++ b/controller/cluster_test.go @@ -109,7 +109,7 @@ func TestCluster_FailureCount(t *testing.T) { mockNode0, mockNode1, mockNode2, mockNode3, }, SlotRanges: []store.SlotRange{{Start: 0, Stop: 16383}}, - MigratingSlot: nil, + MigratingSlot: &store.MigratingSlot{IsMigrating: false}, TargetShardIndex: -1, }}, } @@ -221,7 +221,7 @@ func TestCluster_MigrateSlot(t *testing.T) { }() slotRange, err := store.NewSlotRange(0, 0) require.NoError(t, err) - require.NoError(t, cluster.MigrateSlot(ctx, *slotRange, 1, false)) + require.NoError(t, cluster.MigrateSlot(ctx, slotRange, 1, false)) s := NewMockClusterStore() require.NoError(t, s.CreateCluster(ctx, ns, cluster)) diff --git a/server/api/cluster.go b/server/api/cluster.go index b539c907..b2236446 100644 --- a/server/api/cluster.go +++ b/server/api/cluster.go @@ -33,7 +33,7 @@ import ( type MigrateSlotRequest struct { Target int `json:"target" validate:"required"` - Slot store.SlotRange `json:"slot" validate:"required"` + Slot store.SlotRange `json:"slot" validate:"required"` // we don't use store.MigratingSlot here because we expect a valid SlotRange SlotOnly bool `json:"slot_only"` } diff --git a/server/api/cluster_test.go b/server/api/cluster_test.go index 6559a872..5d3aa8d6 100644 --- a/server/api/cluster_test.go +++ b/server/api/cluster_test.go @@ -131,7 +131,7 @@ func TestClusterBasics(t *testing.T) { slotRange, err := store.NewSlotRange(3, 3) require.NoError(t, err) testMigrateReq := &MigrateSlotRequest{ - Slot: *slotRange, + Slot: slotRange, SlotOnly: true, Target: 1, } @@ -271,7 +271,7 @@ func TestClusterMigrateData(t *testing.T) { currentVersion := gotCluster.Version.Load() sourceSlotRanges := gotCluster.Shards[0].SlotRanges targetSlotRanges := gotCluster.Shards[1].SlotRanges - require.EqualValues(t, slotRange, *gotCluster.Shards[0].MigratingSlot) + require.EqualValues(t, slotRange, gotCluster.Shards[0].MigratingSlot.SlotRange) require.EqualValues(t, 1, gotCluster.Shards[0].TargetShardIndex) // Run the controller to check and update the migration status diff --git a/store/cluster.go b/store/cluster.go index b4bfd9e9..8dff6ed7 100644 --- a/store/cluster.go +++ b/store/cluster.go @@ -181,7 +181,7 @@ func (cluster *Cluster) findShardIndexBySlot(slot SlotRange) (int, error) { for i := 0; i < len(cluster.Shards); i++ { slotRanges := cluster.Shards[i].SlotRanges for _, slotRange := range slotRanges { - if slotRange.HasOverlap(&slot) { + if slotRange.HasOverlap(slot) { if sourceShardIdx != -1 { return sourceShardIdx, consts.ErrSlotRangeBelongsToMultipleShards } @@ -226,7 +226,7 @@ func (cluster *Cluster) MigrateSlot(ctx context.Context, slot SlotRange, targetS } // Will start the data migration in the background - cluster.Shards[sourceShardIdx].MigratingSlot = &slot + cluster.Shards[sourceShardIdx].MigratingSlot = FromSlotRange(slot) cluster.Shards[sourceShardIdx].TargetShardIndex = targetShardIdx return nil } diff --git a/store/cluster_node.go b/store/cluster_node.go index 4da42535..8d038d0d 100644 --- a/store/cluster_node.go +++ b/store/cluster_node.go @@ -85,9 +85,9 @@ type ClusterNode struct { } type ClusterInfo struct { - CurrentEpoch int64 `json:"cluster_current_epoch"` - MigratingSlot *SlotRange `json:"migrating_slot"` - MigratingState string `json:"migrating_state"` + CurrentEpoch int64 `json:"cluster_current_epoch"` + MigratingSlot *MigratingSlot `json:"migrating_slot"` + MigratingState string `json:"migrating_state"` } type ClusterNodeInfo struct { @@ -195,10 +195,11 @@ func (n *ClusterNode) GetClusterInfo(ctx context.Context) (*ClusterInfo, error) } case "migrating_slot", "migrating_slot(s)": // TODO(@git-hulk): handle multiple migrating slots - clusterInfo.MigratingSlot, err = ParseSlotRange(fields[1]) + slotRange, err := ParseSlotRange(fields[1]) if err != nil { return nil, err } + clusterInfo.MigratingSlot = FromSlotRange(*slotRange) case "migrating_state": clusterInfo.MigratingState = fields[1] } diff --git a/store/cluster_shard.go b/store/cluster_shard.go index 62c88269..69ffd4a5 100644 --- a/store/cluster_shard.go +++ b/store/cluster_shard.go @@ -33,11 +33,17 @@ import ( "github.com/apache/kvrocks-controller/consts" ) +const ( + // the old migrating slot was denoted by an int and -1 was + // used to denote a non migrating slot + NotMigratingInt = -1 +) + type Shard struct { - Nodes []Node `json:"nodes"` - SlotRanges []SlotRange `json:"slot_ranges"` - TargetShardIndex int `json:"target_shard_index"` - MigratingSlot *SlotRange `json:"migrating_slot"` + Nodes []Node `json:"nodes"` + SlotRanges []SlotRange `json:"slot_ranges"` + TargetShardIndex int `json:"target_shard_index"` + MigratingSlot *MigratingSlot `json:"migrating_slot"` } type Shards []*Shard @@ -112,7 +118,7 @@ func (shard *Shard) addNode(addr, role, password string) error { } func (shard *Shard) IsMigrating() bool { - return shard.MigratingSlot != nil && shard.TargetShardIndex != -1 + return shard.MigratingSlot != nil && shard.MigratingSlot.IsMigrating && shard.TargetShardIndex != -1 } func (shard *Shard) GetMasterNode() Node { @@ -206,7 +212,7 @@ func (shard *Shard) promoteNewMaster(ctx context.Context, masterNodeID, preferre return preferredNewMasterNode.ID(), nil } -func (shard *Shard) HasOverlap(slotRange *SlotRange) bool { +func (shard *Shard) HasOverlap(slotRange SlotRange) bool { for _, shardSlotRange := range shard.SlotRanges { if shardSlotRange.HasOverlap(slotRange) { return true @@ -261,7 +267,7 @@ func (shard *Shard) UnmarshalJSON(bytes []byte) error { var data struct { SlotRanges []SlotRange `json:"slot_ranges"` TargetShardIndex int `json:"target_shard_index"` - MigratingSlot *SlotRange `json:"migrating_slot"` + MigratingSlot *MigratingSlot `json:"migrating_slot"` Nodes []*ClusterNode `json:"nodes"` } if err := json.Unmarshal(bytes, &data); err != nil { diff --git a/store/cluster_shard_test.go b/store/cluster_shard_test.go index 994046f2..1406f351 100644 --- a/store/cluster_shard_test.go +++ b/store/cluster_shard_test.go @@ -29,11 +29,11 @@ import ( func TestShard_HasOverlap(t *testing.T) { shard := NewShard() - slotRange := &SlotRange{Start: 0, Stop: 100} - shard.SlotRanges = append(shard.SlotRanges, *slotRange) + slotRange := SlotRange{Start: 0, Stop: 100} + shard.SlotRanges = append(shard.SlotRanges, slotRange) require.True(t, shard.HasOverlap(slotRange)) - require.True(t, shard.HasOverlap(&SlotRange{Start: 50, Stop: 150})) - require.False(t, shard.HasOverlap(&SlotRange{Start: 101, Stop: 150})) + require.True(t, shard.HasOverlap(SlotRange{Start: 50, Stop: 150})) + require.False(t, shard.HasOverlap(SlotRange{Start: 101, Stop: 150})) } func TestShard_Sort(t *testing.T) { @@ -56,17 +56,22 @@ func TestShard_Sort(t *testing.T) { func TestShard_IsServicing(t *testing.T) { var err error shard := NewShard() + shard.TargetShardIndex = 0 + shard.MigratingSlot = &MigratingSlot{IsMigrating: false} + require.False(t, shard.IsServicing()) + shard.TargetShardIndex = 0 shard.MigratingSlot = nil require.False(t, shard.IsServicing()) shard.TargetShardIndex = 0 - shard.MigratingSlot, err = NewSlotRange(1, 1) + slotRange, err := NewSlotRange(1, 1) require.Nil(t, err) + shard.MigratingSlot = FromSlotRange(slotRange) require.True(t, shard.IsServicing()) shard.TargetShardIndex = -1 - shard.MigratingSlot = nil + shard.MigratingSlot = &MigratingSlot{IsMigrating: false} shard.SlotRanges = []SlotRange{{Start: 0, Stop: 100}} require.True(t, shard.IsServicing()) diff --git a/store/cluster_test.go b/store/cluster_test.go index 6b6e45c8..975f03f6 100644 --- a/store/cluster_test.go +++ b/store/cluster_test.go @@ -44,19 +44,19 @@ func TestCluster_FindIndexShardBySlot(t *testing.T) { slotRange, err := NewSlotRange(0, 0) require.NoError(t, err) - shard, err := cluster.findShardIndexBySlot(*slotRange) + shard, err := cluster.findShardIndexBySlot(slotRange) require.NoError(t, err) require.Equal(t, 0, shard) slotRange, err = NewSlotRange(MaxSlotID/3+1, MaxSlotID/3+1) require.NoError(t, err) - shard, err = cluster.findShardIndexBySlot(*slotRange) + shard, err = cluster.findShardIndexBySlot(slotRange) require.NoError(t, err) require.Equal(t, 1, shard) slotRange, err = NewSlotRange(MaxSlotID, MaxSlotID) require.NoError(t, err) - shard, err = cluster.findShardIndexBySlot(*slotRange) + shard, err = cluster.findShardIndexBySlot(slotRange) require.NoError(t, err) require.Equal(t, 2, shard) } diff --git a/store/slot.go b/store/slot.go index 04a2b52b..448002eb 100644 --- a/store/slot.go +++ b/store/slot.go @@ -44,24 +44,26 @@ type SlotRange struct { type SlotRanges []SlotRange -func NewSlotRange(start, stop int) (*SlotRange, error) { +type MigratingSlot struct { + SlotRange + IsMigrating bool +} + +func NewSlotRange(start, stop int) (SlotRange, error) { if start > stop { - return nil, errors.New("start was larger than stop") + return SlotRange{}, errors.New("start was larger than stop") } if (start < MinSlotID || start > MaxSlotID) || (stop < MinSlotID || stop > MaxSlotID) { - return nil, ErrSlotOutOfRange + return SlotRange{}, ErrSlotOutOfRange } - return &SlotRange{ + return SlotRange{ Start: start, Stop: stop, }, nil } -func (slotRange *SlotRange) Equal(that *SlotRange) bool { - if that == nil { - return false - } +func (slotRange *SlotRange) Equal(that SlotRange) bool { if slotRange.Start != that.Start { return false } @@ -71,7 +73,7 @@ func (slotRange *SlotRange) Equal(that *SlotRange) bool { return true } -func (slotRange *SlotRange) HasOverlap(that *SlotRange) bool { +func (slotRange *SlotRange) HasOverlap(that SlotRange) bool { return slotRange.Stop >= that.Start && slotRange.Start <= that.Stop } @@ -156,13 +158,84 @@ func (SlotRanges *SlotRanges) Contains(slot int) bool { func (SlotRanges *SlotRanges) HasOverlap(slotRange SlotRange) bool { for _, slotRange := range *SlotRanges { - if slotRange.HasOverlap(&slotRange) { + if slotRange.HasOverlap(slotRange) { return true } } return false } +func (s *SlotRange) Reset() { + s.Start = 0 + s.Stop = 0 +} + +// FromSlotRange will return a MigratingSlot with the IsMigrating field set to true. +// IsMigrating field would probably only be set to false from an unmarshal, like when +// reading from the topology string +func FromSlotRange(slotRange SlotRange) *MigratingSlot { + return &MigratingSlot{ + SlotRange: slotRange, + IsMigrating: true, + } +} + +func (s *MigratingSlot) UnmarshalJSON(data []byte) error { + var slotsString any + if err := json.Unmarshal(data, &slotsString); err != nil { + return err + } + switch t := slotsString.(type) { + case string: + slotRange := SlotRange{} + err := json.Unmarshal(data, &slotRange) + if err != nil { + s.Reset() + return err + } + s.SlotRange = slotRange + s.IsMigrating = true + case float64: + // We use integer to represent the slot because we don't support the slot range + // in the past. So we need to support the integer type for backward compatibility. + // But the number in JSON is float64, so we need to convert it to int here. + if t == NotMigratingInt { + s.Reset() + return nil + } + if t < MinSlotID || t > MaxSlotID { + s.Reset() + return ErrSlotOutOfRange + } + slotID := int(t) + s.Start = slotID + s.Stop = slotID + s.IsMigrating = true + default: + s.Reset() + return fmt.Errorf("invalid slot range type: %T", slotsString) + } + return nil +} + +func (s *MigratingSlot) MarshalJSON() ([]byte, error) { + if !s.IsMigrating { + // backwards compatibility. When we read from an old cluster that had `-1` + // denoting !isMigrating. The MigratingSlot field will not be nil. So when + // this field is marshal'd back into JSON format, we can keep it as it was + // which was `-1`. + // The only case this turns back to null is if a migration happens on this + // shard, and the function `ClearMigrateState()` is called on the shard. + return json.Marshal(NotMigratingInt) + } + return json.Marshal(s.String()) +} + +func (s *MigratingSlot) Reset() { + s.SlotRange.Reset() + s.IsMigrating = false +} + // CanMerge will return true if the given SlotRanges are adjacent with each other func CanMerge(a, b SlotRange) bool { // Ensure a starts before b for easier comparison @@ -218,7 +291,7 @@ func RemoveSlotFromSlotRanges(source SlotRanges, slot SlotRange) SlotRanges { result := make([]SlotRange, 0, len(source)) for _, slotRange := range source { // if no overlap, keep original range - if !slotRange.HasOverlap(&slot) { + if !slotRange.HasOverlap(slot) { result = append(result, slotRange) continue } diff --git a/store/slot_test.go b/store/slot_test.go index 9158198f..119ab097 100644 --- a/store/slot_test.go +++ b/store/slot_test.go @@ -20,6 +20,7 @@ package store import ( + "encoding/json" "testing" "github.com/apache/kvrocks-controller/consts" @@ -42,6 +43,116 @@ func TestSlotRange_String(t *testing.T) { assert.Equal(t, ErrSlotOutOfRange, err) } +func TestMigratingSlot_UnmarshalJSON(t *testing.T) { + var migratingSlot MigratingSlot + + migratingSlot = MigratingSlot{SlotRange: SlotRange{Start: 5, Stop: 5}, IsMigrating: true} // to set values to migratingSlot + slotBytes, err := json.Marshal(NotMigratingInt) + require.NoError(t, err) + err = json.Unmarshal(slotBytes, &migratingSlot) + require.NoError(t, err, "expects no error since -1 was a valid 'not migrating' value") + assert.Equal(t, MigratingSlot{SlotRange{Start: 0, Stop: 0}, false}, migratingSlot) + + migratingSlot = MigratingSlot{SlotRange: SlotRange{Start: 5, Stop: 5}, IsMigrating: true} // to set values to migratingSlot + slotBytes, err = json.Marshal(-5) + require.NoError(t, err) + err = json.Unmarshal(slotBytes, &migratingSlot) + require.ErrorIs(t, err, ErrSlotOutOfRange, "-5 is not a valid 'not migrating' value") + assert.Equal(t, MigratingSlot{SlotRange{Start: 0, Stop: 0}, false}, migratingSlot) + + slotBytes, err = json.Marshal("456") + require.NoError(t, err) + err = json.Unmarshal(slotBytes, &migratingSlot) + require.NoError(t, err) + assert.Equal(t, MigratingSlot{SlotRange{Start: 456, Stop: 456}, true}, migratingSlot) + + slotBytes, err = json.Marshal("123-456") + require.NoError(t, err) + err = json.Unmarshal(slotBytes, &migratingSlot) + require.NoError(t, err) + assert.Equal(t, MigratingSlot{SlotRange{Start: 123, Stop: 456}, true}, migratingSlot) + + slotBytes, err = json.Marshal("invalid-string") + require.NoError(t, err) + err = json.Unmarshal(slotBytes, &migratingSlot) + require.Error(t, err) + assert.Equal(t, MigratingSlot{SlotRange{Start: 0, Stop: 0}, false}, migratingSlot) +} + +// TestMigratingSlot_MarshalUnmarshalJSON will check that we can marshal and then unmarshal +// back into the MigratingSlot +func TestMigratingSlot_MarshalUnmarshalJSON(t *testing.T) { + migratingSlot := MigratingSlot{SlotRange: SlotRange{Start: 5, Stop: 5}, IsMigrating: true} + migratingSlotBytes, err := json.Marshal(&migratingSlot) + require.NoError(t, err) + err = json.Unmarshal(migratingSlotBytes, &migratingSlot) + require.NoError(t, err) + assert.Equal(t, MigratingSlot{SlotRange{Start: 5, Stop: 5}, true}, migratingSlot) + + // tests that we can marshal isMigrating = false, which results in -1, and then unmarshal it + // to be isMigrating = false again + migratingSlot = MigratingSlot{SlotRange: SlotRange{Start: 0, Stop: 0}, IsMigrating: false} + migratingSlotBytes, err = json.Marshal(&migratingSlot) + require.NoError(t, err) + err = json.Unmarshal(migratingSlotBytes, &migratingSlot) + require.NoError(t, err) + assert.Equal(t, MigratingSlot{SlotRange{Start: 0, Stop: 0}, false}, migratingSlot) + + // same test as earlier, but checks that it resets the start and stop + migratingSlot = MigratingSlot{SlotRange: SlotRange{Start: 5, Stop: 5}, IsMigrating: false} + migratingSlotBytes, err = json.Marshal(&migratingSlot) + require.NoError(t, err) + err = json.Unmarshal(migratingSlotBytes, &migratingSlot) + require.NoError(t, err) + assert.Equal(t, MigratingSlot{SlotRange{Start: 0, Stop: 0}, false}, migratingSlot, "expects start and stop to reset to 0") +} + +// TestMigratingSlot_MarshalJSON will checks the resulting string +func TestMigratingSlot_MarshalJSON(t *testing.T) { + migratingSlot := MigratingSlot{SlotRange: SlotRange{Start: 5, Stop: 5}, IsMigrating: true} + migratingSlotBytes, err := json.Marshal(&migratingSlot) + require.NoError(t, err) + assert.Equal(t, `"5"`, string(migratingSlotBytes)) + + migratingSlot = MigratingSlot{SlotRange: SlotRange{Start: 5, Stop: 10}, IsMigrating: true} + migratingSlotBytes, err = json.Marshal(&migratingSlot) + require.NoError(t, err) + assert.Equal(t, `"5-10"`, string(migratingSlotBytes)) + + migratingSlot = MigratingSlot{SlotRange: SlotRange{Start: 5, Stop: 10}, IsMigrating: false} + migratingSlotBytes, err = json.Marshal(&migratingSlot) + require.NoError(t, err) + assert.Equal(t, `-1`, string(migratingSlotBytes)) +} + +func TestMigrateSlotRange_MarshalAndUnmarshalJSON(t *testing.T) { + var slotRange SlotRange + + slotBytes, err := json.Marshal("-100") + require.NoError(t, err) + err = json.Unmarshal(slotBytes, &slotRange) + require.NotNil(t, err, "expects error since input is a negative number") + assert.Equal(t, SlotRange{Start: 0, Stop: 0}, slotRange) + + slotBytes, err = json.Marshal("-100-100000") + require.NoError(t, err) + err = json.Unmarshal(slotBytes, &slotRange) + require.NotNil(t, err, "expects error since input is out of range") + assert.Equal(t, SlotRange{Start: 0, Stop: 0}, slotRange) + + slotBytes, err = json.Marshal("456") + require.NoError(t, err) + err = json.Unmarshal(slotBytes, &slotRange) + require.NoError(t, err) + assert.Equal(t, SlotRange{Start: 456, Stop: 456}, slotRange) + + slotBytes, err = json.Marshal("123-456") + require.NoError(t, err) + err = json.Unmarshal(slotBytes, &slotRange) + require.NoError(t, err) + assert.Equal(t, SlotRange{Start: 123, Stop: 456}, slotRange) +} + func TestSlotRange_Parse(t *testing.T) { sr, err := ParseSlotRange("1-12") assert.Nil(t, err) @@ -82,31 +193,31 @@ func TestAddSlotToSlotRanges(t *testing.T) { } slotRange, err := NewSlotRange(0, 0) require.NoError(t, err) - slotRanges = AddSlotToSlotRanges(slotRanges, *slotRange) + slotRanges = AddSlotToSlotRanges(slotRanges, slotRange) require.Equal(t, 3, len(slotRanges), slotRanges) require.EqualValues(t, SlotRange{Start: 0, Stop: 20}, slotRanges[0], slotRanges) slotRange, err = NewSlotRange(21, 21) require.NoError(t, err) - slotRanges = AddSlotToSlotRanges(slotRanges, *slotRange) + slotRanges = AddSlotToSlotRanges(slotRanges, slotRange) require.Equal(t, 3, len(slotRanges), slotRanges) require.EqualValues(t, SlotRange{Start: 0, Stop: 21}, slotRanges[0], slotRanges) slotRange, err = NewSlotRange(50, 50) require.NoError(t, err) - slotRanges = AddSlotToSlotRanges(slotRanges, *slotRange) + slotRanges = AddSlotToSlotRanges(slotRanges, slotRange) require.Equal(t, 4, len(slotRanges), slotRanges) require.EqualValues(t, SlotRange{Start: 50, Stop: 50}, slotRanges[1], slotRanges) slotRange, err = NewSlotRange(200, 200) require.NoError(t, err) - slotRanges = AddSlotToSlotRanges(slotRanges, *slotRange) + slotRanges = AddSlotToSlotRanges(slotRanges, slotRange) require.Equal(t, 3, len(slotRanges), slotRanges) require.EqualValues(t, SlotRange{Start: 101, Stop: 300}, slotRanges[2], slotRanges) slotRange, err = NewSlotRange(400, 400) require.NoError(t, err) - slotRanges = AddSlotToSlotRanges(slotRanges, *slotRange) + slotRanges = AddSlotToSlotRanges(slotRanges, slotRange) require.Equal(t, 4, len(slotRanges), slotRanges) require.EqualValues(t, SlotRange{Start: 400, Stop: 400}, slotRanges[3], slotRanges) } @@ -119,56 +230,56 @@ func TestRemoveSlotRanges(t *testing.T) { } slotRange, err := NewSlotRange(0, 0) require.NoError(t, err) - slotRanges = RemoveSlotFromSlotRanges(slotRanges, *slotRange) + slotRanges = RemoveSlotFromSlotRanges(slotRanges, slotRange) require.Equal(t, 3, len(slotRanges), slotRanges) require.EqualValues(t, SlotRange{Start: 1, Stop: 20}, slotRanges[0], slotRanges) slotRange, err = NewSlotRange(21, 21) require.NoError(t, err) - slotRanges = RemoveSlotFromSlotRanges(slotRanges, *slotRange) + slotRanges = RemoveSlotFromSlotRanges(slotRanges, slotRange) require.Equal(t, 3, len(slotRanges), slotRanges) require.EqualValues(t, SlotRange{Start: 1, Stop: 20}, slotRanges[0], slotRanges) slotRange, err = NewSlotRange(20, 20) require.NoError(t, err) - slotRanges = RemoveSlotFromSlotRanges(slotRanges, *slotRange) + slotRanges = RemoveSlotFromSlotRanges(slotRanges, slotRange) require.Equal(t, 3, len(slotRanges), slotRanges) require.EqualValues(t, SlotRange{Start: 1, Stop: 19}, slotRanges[0], slotRanges) slotRange, err = NewSlotRange(150, 150) require.NoError(t, err) - slotRanges = RemoveSlotFromSlotRanges(slotRanges, *slotRange) + slotRanges = RemoveSlotFromSlotRanges(slotRanges, slotRange) require.Equal(t, 4, len(slotRanges), slotRanges) require.EqualValues(t, SlotRange{Start: 101, Stop: 149}, slotRanges[1], slotRanges) slotRange, err = NewSlotRange(101, 101) require.NoError(t, err) - slotRanges = RemoveSlotFromSlotRanges(slotRanges, *slotRange) + slotRanges = RemoveSlotFromSlotRanges(slotRanges, slotRange) require.Equal(t, 4, len(slotRanges), slotRanges) require.EqualValues(t, SlotRange{Start: 102, Stop: 149}, slotRanges[1], slotRanges) slotRange, err = NewSlotRange(199, 199) require.NoError(t, err) - slotRanges = RemoveSlotFromSlotRanges(slotRanges, *slotRange) + slotRanges = RemoveSlotFromSlotRanges(slotRanges, slotRange) require.Equal(t, 4, len(slotRanges), slotRanges) require.EqualValues(t, SlotRange{Start: 151, Stop: 198}, slotRanges[2], slotRanges) slotRange, err = NewSlotRange(300, 300) require.NoError(t, err) - slotRanges = RemoveSlotFromSlotRanges(slotRanges, *slotRange) + slotRanges = RemoveSlotFromSlotRanges(slotRanges, slotRange) require.Equal(t, 4, len(slotRanges), slotRanges) require.EqualValues(t, SlotRange{Start: 201, Stop: 299}, slotRanges[3], slotRanges) slotRange, err = NewSlotRange(298, 298) require.NoError(t, err) - slotRanges = RemoveSlotFromSlotRanges(slotRanges, *slotRange) + slotRanges = RemoveSlotFromSlotRanges(slotRanges, slotRange) require.Equal(t, 5, len(slotRanges), slotRanges) require.EqualValues(t, SlotRange{Start: 201, Stop: 297}, slotRanges[3], slotRanges) require.EqualValues(t, SlotRange{Start: 299, Stop: 299}, slotRanges[4], slotRanges) slotRange, err = NewSlotRange(299, 299) require.NoError(t, err) - slotRanges = RemoveSlotFromSlotRanges(slotRanges, *slotRange) + slotRanges = RemoveSlotFromSlotRanges(slotRanges, slotRange) require.Equal(t, 4, len(slotRanges), slotRanges) require.EqualValues(t, SlotRange{Start: 201, Stop: 297}, slotRanges[3], slotRanges) } @@ -187,7 +298,7 @@ func TestSlotRange_HasOverlap(t *testing.T) { Stop int } type args struct { - that *SlotRange + that SlotRange } tests := []struct { name string @@ -198,43 +309,43 @@ func TestSlotRange_HasOverlap(t *testing.T) { { name: "0-5 does not overlap 6-7", fields: fields{Start: 0, Stop: 5}, - args: args{&SlotRange{Start: 6, Stop: 7}}, + args: args{SlotRange{Start: 6, Stop: 7}}, want: false, }, { name: "0-5 does overlap 3-4", fields: fields{Start: 0, Stop: 5}, - args: args{&SlotRange{Start: 3, Stop: 4}}, + args: args{SlotRange{Start: 3, Stop: 4}}, want: true, }, { name: "0-5 does overlap 5-8", fields: fields{Start: 0, Stop: 5}, - args: args{&SlotRange{Start: 5, Stop: 8}}, + args: args{SlotRange{Start: 5, Stop: 8}}, want: true, }, { name: "0-5 does overlap 4-8", fields: fields{Start: 0, Stop: 5}, - args: args{&SlotRange{Start: 4, Stop: 8}}, + args: args{SlotRange{Start: 4, Stop: 8}}, want: true, }, { name: "0-100 does not overlap 101-150", fields: fields{Start: 0, Stop: 100}, - args: args{&SlotRange{Start: 101, Stop: 150}}, + args: args{SlotRange{Start: 101, Stop: 150}}, want: false, }, { name: "50-100 does overlap 30-50", fields: fields{Start: 50, Stop: 100}, - args: args{&SlotRange{Start: 30, Stop: 50}}, + args: args{SlotRange{Start: 30, Stop: 50}}, want: true, }, { name: "50-100 does overlap 50-51", fields: fields{Start: 50, Stop: 100}, - args: args{&SlotRange{Start: 50, Stop: 51}}, + args: args{SlotRange{Start: 50, Stop: 51}}, want: true, }, }