github.com/filecoin-project/specs-actors/v4@v4.0.2/actors/builtin/miner/deadline_assignment_test.go (about) 1 package miner 2 3 import ( 4 "testing" 5 6 "github.com/filecoin-project/go-state-types/abi" 7 "github.com/stretchr/testify/assert" 8 "github.com/stretchr/testify/require" 9 ) 10 11 func TestDeadlineAssignment(t *testing.T) { 12 const partitionSize = 4 13 const maxPartitions = 100 14 15 type deadline struct { 16 liveSectors, deadSectors uint64 17 expectSectors []uint64 18 } 19 20 type testCase struct { 21 sectors uint64 22 deadlines [WPoStPeriodDeadlines]*deadline 23 } 24 25 testCases := []testCase{{ 26 // Even assignment and striping. 27 sectors: 10, 28 deadlines: [WPoStPeriodDeadlines]*deadline{ 29 0: { 30 expectSectors: []uint64{ 31 0, 1, 2, 3, 32 8, 9, 33 }, 34 }, 35 1: { 36 expectSectors: []uint64{ 37 4, 5, 6, 7, 38 }, 39 }, 40 }, 41 }, { 42 // Fill non-full first 43 sectors: 5, 44 deadlines: [WPoStPeriodDeadlines]*deadline{ 45 0: { 46 expectSectors: []uint64{3, 4}, 47 }, 48 1: {}, // expect nothing. 49 3: { 50 liveSectors: 1, 51 expectSectors: []uint64{0, 1, 2}, 52 }, 53 }, 54 }, { 55 // Assign to deadline with least number of live partitions. 56 sectors: 1, 57 deadlines: [WPoStPeriodDeadlines]*deadline{ 58 0: { 59 // 2 live partitions. +1 would add another. 60 liveSectors: 8, 61 }, 62 1: { 63 // 2 live partitions. +1 wouldn't add another. 64 // 1 dead partition. 65 liveSectors: 7, 66 deadSectors: 5, 67 expectSectors: []uint64{0}, 68 }, 69 }, 70 }, { 71 // Avoid increasing max partitions. Both deadlines have the same 72 // number of partitions post-compaction, but deadline 1 has 73 // fewer pre-compaction. 74 sectors: 1, 75 deadlines: [WPoStPeriodDeadlines]*deadline{ 76 0: { 77 // one live, one dead. 78 liveSectors: 4, 79 deadSectors: 4, 80 }, 81 1: { 82 // 1 live partitions. +1 would add another. 83 liveSectors: 4, 84 expectSectors: []uint64{0}, 85 }, 86 }, 87 }, { 88 // With multiple open partitions, assign to most full first. 89 sectors: 1, 90 deadlines: [WPoStPeriodDeadlines]*deadline{ 91 0: { 92 liveSectors: 1, 93 }, 94 1: { 95 liveSectors: 2, 96 expectSectors: []uint64{0}, 97 }, 98 }, 99 }, { 100 // dead sectors also count 101 sectors: 1, 102 deadlines: [WPoStPeriodDeadlines]*deadline{ 103 0: { 104 liveSectors: 1, 105 }, 106 1: { 107 deadSectors: 2, 108 expectSectors: []uint64{0}, 109 }, 110 }, 111 }, { 112 // dead sectors really do count. 113 sectors: 1, 114 deadlines: [WPoStPeriodDeadlines]*deadline{ 115 0: { 116 deadSectors: 1, 117 }, 118 1: { 119 deadSectors: 2, 120 expectSectors: []uint64{0}, 121 }, 122 }, 123 }, { 124 // when partitions are equally full, assign based on live sectors. 125 sectors: 1, 126 deadlines: [WPoStPeriodDeadlines]*deadline{ 127 0: { 128 liveSectors: 1, 129 deadSectors: 1, 130 }, 131 1: { 132 deadSectors: 2, 133 expectSectors: []uint64{0}, 134 }, 135 }, 136 }} 137 138 for _, tc := range testCases { 139 var deadlines [WPoStPeriodDeadlines]*Deadline 140 for i := range deadlines { 141 dl := tc.deadlines[i] 142 if dl == nil { 143 // blackout 144 continue 145 } 146 deadlines[i] = &Deadline{ 147 LiveSectors: dl.liveSectors, 148 TotalSectors: dl.liveSectors + dl.deadSectors, 149 } 150 } 151 sectors := make([]*SectorOnChainInfo, tc.sectors) 152 for i := range sectors { 153 sectors[i] = &SectorOnChainInfo{SectorNumber: abi.SectorNumber(i)} 154 } 155 assignment, err := assignDeadlines(maxPartitions, partitionSize, &deadlines, sectors) 156 require.NoError(t, err) 157 for i, sectors := range assignment { 158 dl := tc.deadlines[i] 159 // blackout? 160 if dl == nil { 161 assert.Empty(t, sectors, "expected no sectors to have been assigned to blacked out deadline") 162 continue 163 } 164 require.Equal(t, len(dl.expectSectors), len(sectors), "for deadline %d", i) 165 166 for i, expectedSectorNo := range dl.expectSectors { 167 assert.Equal(t, uint64(sectors[i].SectorNumber), expectedSectorNo) 168 } 169 } 170 } 171 } 172 173 func TestMaxPartitionsPerDeadline(t *testing.T) { 174 const maxPartitions = 5 175 const partitionSize = 5 176 177 t.Run("fails if all deadlines hit their max partitions limit before assigning all sectors to deadlines", func(T *testing.T) { 178 // one deadline can take 5 * 5 = 25 sectors 179 // so 48 deadlines can take 48 * 25 = 1200 sectors. 180 // Hence, we should fail if we try to assign 1201 sectors. 181 182 var deadlines [WPoStPeriodDeadlines]*Deadline 183 for i := range deadlines { 184 deadlines[i] = &Deadline{ 185 LiveSectors: 0, 186 TotalSectors: 0, 187 } 188 } 189 190 sectors := make([]*SectorOnChainInfo, 1201) 191 for i := range sectors { 192 sectors[i] = &SectorOnChainInfo{SectorNumber: abi.SectorNumber(i)} 193 } 194 195 _, err := assignDeadlines(maxPartitions, partitionSize, &deadlines, sectors) 196 require.Error(t, err) 197 }) 198 199 t.Run("succeeds if all all deadlines hit their max partitions limit but assignment is complete", func(t *testing.T) { 200 // one deadline can take 5 * 5 = 25 sectors 201 // so 48 deadlines that can take 48 * 25 = 1200 sectors. 202 var deadlines [WPoStPeriodDeadlines]*Deadline 203 for i := range deadlines { 204 deadlines[i] = &Deadline{ 205 LiveSectors: 0, 206 TotalSectors: 0, 207 } 208 } 209 210 sectors := make([]*SectorOnChainInfo, 1200) 211 for i := range sectors { 212 sectors[i] = &SectorOnChainInfo{SectorNumber: abi.SectorNumber(i)} 213 } 214 215 deadlineToSectors, err := assignDeadlines(maxPartitions, partitionSize, &deadlines, sectors) 216 require.NoError(t, err) 217 218 for _, sectors := range deadlineToSectors { 219 require.Len(t, sectors, 25) // there should be (1200/48) = 25 sectors per deadline 220 } 221 }) 222 223 t.Run("fails if some deadlines have sectors beforehand and all deadlines hit their max partition limit", func(t *testing.T) { 224 var deadlines [WPoStPeriodDeadlines]*Deadline 225 for i := range deadlines { 226 deadlines[i] = &Deadline{ 227 LiveSectors: 1, 228 TotalSectors: 2, 229 } 230 } 231 232 // can only take 1200 - (2 * 48) = 1104 sectors 233 234 sectors := make([]*SectorOnChainInfo, 1105) 235 for i := range sectors { 236 sectors[i] = &SectorOnChainInfo{SectorNumber: abi.SectorNumber(i)} 237 } 238 239 _, err := assignDeadlines(maxPartitions, partitionSize, &deadlines, sectors) 240 require.Error(t, err) 241 }) 242 }