github.com/m3db/m3@v1.5.0/src/cluster/placement/planner/planner_test.go (about)

     1  // Copyright (c) 2016 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 planner
    22  
    23  import (
    24  	"sort"
    25  	"testing"
    26  
    27  	"github.com/m3db/m3/src/cluster/placement"
    28  	"github.com/m3db/m3/src/cluster/shard"
    29  
    30  	"github.com/stretchr/testify/assert"
    31  )
    32  
    33  func TestDeployment(t *testing.T) {
    34  	i1 := placement.NewEmptyInstance("i1", "r1", "z1", "endpoint", 1)
    35  	i1.Shards().Add(shard.NewShard(1).SetState(shard.Available))
    36  	i1.Shards().Add(shard.NewShard(2).SetState(shard.Available))
    37  	i1.Shards().Add(shard.NewShard(3).SetState(shard.Available))
    38  
    39  	i2 := placement.NewEmptyInstance("i2", "r2", "z1", "endpoint", 1)
    40  	i2.Shards().Add(shard.NewShard(4).SetState(shard.Available))
    41  	i2.Shards().Add(shard.NewShard(5).SetState(shard.Available))
    42  	i2.Shards().Add(shard.NewShard(6).SetState(shard.Available))
    43  
    44  	i3 := placement.NewEmptyInstance("i3", "r3", "z1", "endpoint", 1)
    45  	i3.Shards().Add(shard.NewShard(1).SetState(shard.Available))
    46  	i3.Shards().Add(shard.NewShard(3).SetState(shard.Available))
    47  	i3.Shards().Add(shard.NewShard(5).SetState(shard.Available))
    48  
    49  	i4 := placement.NewEmptyInstance("i4", "r4", "z1", "endpoint", 1)
    50  	i4.Shards().Add(shard.NewShard(2).SetState(shard.Available))
    51  	i4.Shards().Add(shard.NewShard(4).SetState(shard.Available))
    52  	i4.Shards().Add(shard.NewShard(6).SetState(shard.Available))
    53  
    54  	i5 := placement.NewEmptyInstance("i5", "r5", "z1", "endpoint", 1)
    55  	i5.Shards().Add(shard.NewShard(5).SetState(shard.Available))
    56  	i5.Shards().Add(shard.NewShard(6).SetState(shard.Available))
    57  	i5.Shards().Add(shard.NewShard(1).SetState(shard.Available))
    58  
    59  	i6 := placement.NewEmptyInstance("i6", "r6", "z1", "endpoint", 1)
    60  	i6.Shards().Add(shard.NewShard(2).SetState(shard.Available))
    61  	i6.Shards().Add(shard.NewShard(3).SetState(shard.Available))
    62  	i6.Shards().Add(shard.NewShard(4).SetState(shard.Available))
    63  
    64  	instances := []placement.Instance{i1, i2, i3, i4, i5, i6}
    65  
    66  	mp := placement.NewPlacement().
    67  		SetInstances(instances).
    68  		SetShards([]uint32{1, 2, 3, 4, 5, 6}).
    69  		SetReplicaFactor(3)
    70  
    71  	dp := NewShardAwareDeploymentPlanner(placement.NewDeploymentOptions())
    72  	steps := dp.DeploymentSteps(mp)
    73  	total := 0
    74  	for _, step := range steps {
    75  		total += len(step)
    76  	}
    77  	assert.Equal(t, total, 6)
    78  	assert.True(t, len(steps) == 3)
    79  }
    80  
    81  func TestDeterministicSteps(t *testing.T) {
    82  	i1 := placement.NewEmptyInstance("i1", "r1", "z1", "endpoint", 1)
    83  	i1.Shards().Add(shard.NewShard(1).SetState(shard.Available))
    84  	i1.Shards().Add(shard.NewShard(2).SetState(shard.Available))
    85  
    86  	i2 := placement.NewEmptyInstance("i2", "r2", "z1", "endpoint", 1)
    87  	i2.Shards().Add(shard.NewShard(3).SetState(shard.Available))
    88  	i2.Shards().Add(shard.NewShard(4).SetState(shard.Available))
    89  
    90  	i3 := placement.NewEmptyInstance("i3", "r3", "z1", "endpoint", 1)
    91  	i3.Shards().Add(shard.NewShard(5).SetState(shard.Available))
    92  	i3.Shards().Add(shard.NewShard(6).SetState(shard.Available))
    93  
    94  	i4 := placement.NewEmptyInstance("i4", "r4", "z1", "endpoint", 1)
    95  	i4.Shards().Add(shard.NewShard(1).SetState(shard.Available))
    96  	i4.Shards().Add(shard.NewShard(3).SetState(shard.Available))
    97  
    98  	i5 := placement.NewEmptyInstance("i5", "r5", "z1", "endpoint", 1)
    99  	i5.Shards().Add(shard.NewShard(4).SetState(shard.Available))
   100  	i5.Shards().Add(shard.NewShard(6).SetState(shard.Available))
   101  
   102  	i6 := placement.NewEmptyInstance("i6", "r6", "z1", "endpoint", 1)
   103  	i6.Shards().Add(shard.NewShard(2).SetState(shard.Available))
   104  	i6.Shards().Add(shard.NewShard(5).SetState(shard.Available))
   105  
   106  	h7 := placement.NewEmptyInstance("i7", "r7", "z1", "endpoint", 1)
   107  	h7.Shards().Add(shard.NewShard(2).SetState(shard.Available))
   108  	h7.Shards().Add(shard.NewShard(3).SetState(shard.Available))
   109  
   110  	h8 := placement.NewEmptyInstance("i8", "r8", "z1", "endpoint", 1)
   111  	h8.Shards().Add(shard.NewShard(4).SetState(shard.Available))
   112  	h8.Shards().Add(shard.NewShard(5).SetState(shard.Available))
   113  
   114  	h9 := placement.NewEmptyInstance("i9", "r9", "z1", "endpoint", 1)
   115  	h9.Shards().Add(shard.NewShard(6).SetState(shard.Available))
   116  	h9.Shards().Add(shard.NewShard(1).SetState(shard.Available))
   117  
   118  	mp1 := placement.NewPlacement().
   119  		SetInstances([]placement.Instance{i1, i2, i3, i4, i5, i6, h7, h8, h9}).
   120  		SetShards([]uint32{1, 2, 3, 4, 5, 6}).
   121  		SetReplicaFactor(3)
   122  
   123  	mp2 := placement.NewPlacement().
   124  		SetInstances([]placement.Instance{i4, i5, i6, h7, h8, h9, i1, i2, i3}).
   125  		SetShards([]uint32{1, 2, 3, 4, 5, 6}).
   126  		SetReplicaFactor(3)
   127  
   128  	dp := NewShardAwareDeploymentPlanner(placement.NewDeploymentOptions())
   129  	assert.Equal(t, dp.DeploymentSteps(mp1), dp.DeploymentSteps(mp2))
   130  }
   131  
   132  func TestDeploymentWithThreeReplica(t *testing.T) {
   133  	i1 := placement.NewEmptyInstance("i1", "r1", "z1", "endpoint", 1)
   134  	i1.Shards().Add(shard.NewShard(1).SetState(shard.Available))
   135  	i1.Shards().Add(shard.NewShard(2).SetState(shard.Available))
   136  
   137  	i2 := placement.NewEmptyInstance("i2", "r2", "z1", "endpoint", 1)
   138  	i2.Shards().Add(shard.NewShard(3).SetState(shard.Available))
   139  	i2.Shards().Add(shard.NewShard(4).SetState(shard.Available))
   140  
   141  	i3 := placement.NewEmptyInstance("i3", "r3", "z1", "endpoint", 1)
   142  	i3.Shards().Add(shard.NewShard(5).SetState(shard.Available))
   143  	i3.Shards().Add(shard.NewShard(6).SetState(shard.Available))
   144  
   145  	i4 := placement.NewEmptyInstance("i4", "r4", "z1", "endpoint", 1)
   146  	i4.Shards().Add(shard.NewShard(1).SetState(shard.Available))
   147  	i4.Shards().Add(shard.NewShard(3).SetState(shard.Available))
   148  
   149  	i5 := placement.NewEmptyInstance("i5", "r5", "z1", "endpoint", 1)
   150  	i5.Shards().Add(shard.NewShard(4).SetState(shard.Available))
   151  	i5.Shards().Add(shard.NewShard(6).SetState(shard.Available))
   152  
   153  	i6 := placement.NewEmptyInstance("i6", "r6", "z1", "endpoint", 1)
   154  	i6.Shards().Add(shard.NewShard(2).SetState(shard.Available))
   155  	i6.Shards().Add(shard.NewShard(5).SetState(shard.Available))
   156  
   157  	h7 := placement.NewEmptyInstance("i7", "r7", "z1", "endpoint", 1)
   158  	h7.Shards().Add(shard.NewShard(2).SetState(shard.Available))
   159  	h7.Shards().Add(shard.NewShard(3).SetState(shard.Available))
   160  
   161  	h8 := placement.NewEmptyInstance("i8", "r8", "z1", "endpoint", 1)
   162  	h8.Shards().Add(shard.NewShard(4).SetState(shard.Available))
   163  	h8.Shards().Add(shard.NewShard(5).SetState(shard.Available))
   164  
   165  	h9 := placement.NewEmptyInstance("i9", "r9", "z1", "endpoint", 1)
   166  	h9.Shards().Add(shard.NewShard(6).SetState(shard.Available))
   167  	h9.Shards().Add(shard.NewShard(1).SetState(shard.Available))
   168  
   169  	instances := []placement.Instance{i1, i2, i3, i4, i5, i6, h7, h8, h9}
   170  
   171  	mp := placement.NewPlacement().
   172  		SetInstances(instances).
   173  		SetShards([]uint32{1, 2, 3, 4, 5, 6}).
   174  		SetReplicaFactor(3)
   175  
   176  	dp := NewShardAwareDeploymentPlanner(placement.NewDeploymentOptions())
   177  	steps := dp.DeploymentSteps(mp)
   178  	total := 0
   179  	for _, step := range steps {
   180  		total += len(step)
   181  	}
   182  	assert.Equal(t, total, 9)
   183  	assert.True(t, len(steps) == 3)
   184  
   185  	dp = NewShardAwareDeploymentPlanner(placement.NewDeploymentOptions().SetMaxStepSize(2))
   186  	steps = dp.DeploymentSteps(mp)
   187  	total = 0
   188  	for _, step := range steps {
   189  		total += len(step)
   190  	}
   191  	assert.Equal(t, total, 9)
   192  	assert.True(t, len(steps) == 5)
   193  
   194  	dp = NewShardAwareDeploymentPlanner(placement.NewDeploymentOptions().SetMaxStepSize(1))
   195  	steps = dp.DeploymentSteps(mp)
   196  	total = 0
   197  	for _, step := range steps {
   198  		total += len(step)
   199  	}
   200  	assert.Equal(t, total, 9)
   201  	assert.True(t, len(steps) == 9)
   202  }
   203  
   204  func TestRemoveInstance(t *testing.T) {
   205  	i1 := placement.NewEmptyInstance("i1", "r1", "z1", "", 1)
   206  	i2 := placement.NewEmptyInstance("i2", "r2", "z1", "", 1)
   207  	i3 := placement.NewEmptyInstance("i3", "r3", "z1", "", 1)
   208  	i4 := placement.NewEmptyInstance("i4", "r4", "z1", "", 1)
   209  
   210  	instances := []placement.Instance{i1, i2, i3, i4}
   211  
   212  	left := removeInstance(instances, i4)
   213  	assert.Equal(t, 3, len(left))
   214  
   215  	left = removeInstance(instances, placement.NewEmptyInstance("i5", "r5", "z1", "", 1))
   216  	assert.Equal(t, 4, len(left))
   217  }
   218  
   219  func TestSort(t *testing.T) {
   220  	var steps sortableSteps
   221  	steps = append(steps, []placement.Instance{
   222  		placement.NewEmptyInstance("", "", "", "", 1),
   223  		placement.NewEmptyInstance("", "", "", "", 1)})
   224  	steps = append(steps, []placement.Instance{
   225  		placement.NewEmptyInstance("", "", "", "", 1),
   226  		placement.NewEmptyInstance("", "", "", "", 1),
   227  		placement.NewEmptyInstance("", "", "", "", 1)})
   228  	steps = append(steps, []placement.Instance{
   229  		placement.NewEmptyInstance("", "", "", "", 1)})
   230  	sort.Sort(steps)
   231  
   232  	assert.Equal(t, 3, len(steps))
   233  	assert.Equal(t, 3, len(steps[0]))
   234  	assert.Equal(t, 2, len(steps[1]))
   235  	assert.Equal(t, 1, len(steps[2]))
   236  }