command_volume_fix_replication_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. package shell
  2. import (
  3. "testing"
  4. "github.com/chrislusf/seaweedfs/weed/pb/master_pb"
  5. "github.com/chrislusf/seaweedfs/weed/storage/super_block"
  6. )
  7. type testcase struct {
  8. name string
  9. replication string
  10. replicas []*VolumeReplica
  11. possibleLocation location
  12. expected bool
  13. }
  14. func TestSatisfyReplicaPlacementComplicated(t *testing.T) {
  15. var tests = []testcase{
  16. {
  17. name: "test 100 negative",
  18. replication: "100",
  19. replicas: []*VolumeReplica{
  20. {
  21. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
  22. },
  23. },
  24. possibleLocation: location{"dc1", "r2", &master_pb.DataNodeInfo{Id: "dn2"}},
  25. expected: false,
  26. },
  27. {
  28. name: "test 100 positive",
  29. replication: "100",
  30. replicas: []*VolumeReplica{
  31. {
  32. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
  33. },
  34. },
  35. possibleLocation: location{"dc2", "r2", &master_pb.DataNodeInfo{Id: "dn2"}},
  36. expected: true,
  37. },
  38. {
  39. name: "test 022 positive",
  40. replication: "022",
  41. replicas: []*VolumeReplica{
  42. {
  43. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
  44. },
  45. {
  46. location: &location{"dc1", "r2", &master_pb.DataNodeInfo{Id: "dn2"}},
  47. },
  48. {
  49. location: &location{"dc1", "r3", &master_pb.DataNodeInfo{Id: "dn3"}},
  50. },
  51. },
  52. possibleLocation: location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn4"}},
  53. expected: true,
  54. },
  55. {
  56. name: "test 022 negative",
  57. replication: "022",
  58. replicas: []*VolumeReplica{
  59. {
  60. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
  61. },
  62. {
  63. location: &location{"dc1", "r2", &master_pb.DataNodeInfo{Id: "dn2"}},
  64. },
  65. {
  66. location: &location{"dc1", "r3", &master_pb.DataNodeInfo{Id: "dn3"}},
  67. },
  68. },
  69. possibleLocation: location{"dc1", "r4", &master_pb.DataNodeInfo{Id: "dn4"}},
  70. expected: false,
  71. },
  72. {
  73. name: "test 210 moved from 200 positive",
  74. replication: "210",
  75. replicas: []*VolumeReplica{
  76. {
  77. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
  78. },
  79. {
  80. location: &location{"dc2", "r2", &master_pb.DataNodeInfo{Id: "dn2"}},
  81. },
  82. {
  83. location: &location{"dc3", "r3", &master_pb.DataNodeInfo{Id: "dn3"}},
  84. },
  85. },
  86. possibleLocation: location{"dc1", "r4", &master_pb.DataNodeInfo{Id: "dn4"}},
  87. expected: true,
  88. },
  89. {
  90. name: "test 210 moved from 200 negative extra dc",
  91. replication: "210",
  92. replicas: []*VolumeReplica{
  93. {
  94. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
  95. },
  96. {
  97. location: &location{"dc2", "r2", &master_pb.DataNodeInfo{Id: "dn2"}},
  98. },
  99. {
  100. location: &location{"dc3", "r3", &master_pb.DataNodeInfo{Id: "dn3"}},
  101. },
  102. },
  103. possibleLocation: location{"dc4", "r4", &master_pb.DataNodeInfo{Id: "dn4"}},
  104. expected: false,
  105. },
  106. {
  107. name: "test 210 moved from 200 negative extra data node",
  108. replication: "210",
  109. replicas: []*VolumeReplica{
  110. {
  111. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
  112. },
  113. {
  114. location: &location{"dc2", "r2", &master_pb.DataNodeInfo{Id: "dn2"}},
  115. },
  116. {
  117. location: &location{"dc3", "r3", &master_pb.DataNodeInfo{Id: "dn3"}},
  118. },
  119. },
  120. possibleLocation: location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn4"}},
  121. expected: false,
  122. },
  123. }
  124. runTests(tests, t)
  125. }
  126. func TestSatisfyReplicaPlacement01x(t *testing.T) {
  127. var tests = []testcase{
  128. {
  129. name: "test 011 same existing rack",
  130. replication: "011",
  131. replicas: []*VolumeReplica{
  132. {
  133. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
  134. },
  135. {
  136. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn2"}},
  137. },
  138. },
  139. possibleLocation: location{"dc1", "r2", &master_pb.DataNodeInfo{Id: "dn3"}},
  140. expected: true,
  141. },
  142. {
  143. name: "test 011 negative",
  144. replication: "011",
  145. replicas: []*VolumeReplica{
  146. {
  147. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
  148. },
  149. {
  150. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn2"}},
  151. },
  152. },
  153. possibleLocation: location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn3"}},
  154. expected: false,
  155. },
  156. {
  157. name: "test 011 different existing racks",
  158. replication: "011",
  159. replicas: []*VolumeReplica{
  160. {
  161. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
  162. },
  163. {
  164. location: &location{"dc1", "r2", &master_pb.DataNodeInfo{Id: "dn2"}},
  165. },
  166. },
  167. possibleLocation: location{"dc1", "r2", &master_pb.DataNodeInfo{Id: "dn3"}},
  168. expected: true,
  169. },
  170. {
  171. name: "test 011 different existing racks negative",
  172. replication: "011",
  173. replicas: []*VolumeReplica{
  174. {
  175. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
  176. },
  177. {
  178. location: &location{"dc1", "r2", &master_pb.DataNodeInfo{Id: "dn2"}},
  179. },
  180. },
  181. possibleLocation: location{"dc1", "r3", &master_pb.DataNodeInfo{Id: "dn3"}},
  182. expected: false,
  183. },
  184. }
  185. runTests(tests, t)
  186. }
  187. func TestSatisfyReplicaPlacement00x(t *testing.T) {
  188. var tests = []testcase{
  189. {
  190. name: "test 001",
  191. replication: "001",
  192. replicas: []*VolumeReplica{
  193. {
  194. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
  195. },
  196. },
  197. possibleLocation: location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn2"}},
  198. expected: true,
  199. },
  200. {
  201. name: "test 002 positive",
  202. replication: "002",
  203. replicas: []*VolumeReplica{
  204. {
  205. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
  206. },
  207. {
  208. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn2"}},
  209. },
  210. },
  211. possibleLocation: location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn3"}},
  212. expected: true,
  213. },
  214. {
  215. name: "test 002 negative, repeat the same node",
  216. replication: "002",
  217. replicas: []*VolumeReplica{
  218. {
  219. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
  220. },
  221. {
  222. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn2"}},
  223. },
  224. },
  225. possibleLocation: location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn2"}},
  226. expected: false,
  227. },
  228. {
  229. name: "test 002 negative, enough node already",
  230. replication: "002",
  231. replicas: []*VolumeReplica{
  232. {
  233. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
  234. },
  235. {
  236. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn2"}},
  237. },
  238. {
  239. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn3"}},
  240. },
  241. },
  242. possibleLocation: location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn4"}},
  243. expected: false,
  244. },
  245. }
  246. runTests(tests, t)
  247. }
  248. func TestSatisfyReplicaPlacement100(t *testing.T) {
  249. var tests = []testcase{
  250. {
  251. name: "test 100",
  252. replication: "100",
  253. replicas: []*VolumeReplica{
  254. {
  255. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
  256. },
  257. {
  258. location: &location{"dc1", "r2", &master_pb.DataNodeInfo{Id: "dn2"}},
  259. },
  260. },
  261. possibleLocation: location{"dc2", "r3", &master_pb.DataNodeInfo{Id: "dn3"}},
  262. expected: true,
  263. },
  264. }
  265. runTests(tests, t)
  266. }
  267. func runTests(tests []testcase, t *testing.T) {
  268. for _, tt := range tests {
  269. replicaPlacement, _ := super_block.NewReplicaPlacementFromString(tt.replication)
  270. println("replication:", tt.replication, "expected", tt.expected, "name:", tt.name)
  271. if satisfyReplicaPlacement(replicaPlacement, tt.replicas, tt.possibleLocation) != tt.expected {
  272. t.Errorf("%s: expect %v add %v to %s %+v",
  273. tt.name, tt.expected, tt.possibleLocation, tt.replication, tt.replicas)
  274. }
  275. }
  276. }
  277. func TestMisplacedChecking(t *testing.T) {
  278. var tests = []testcase{
  279. {
  280. name: "test 001",
  281. replication: "001",
  282. replicas: []*VolumeReplica{
  283. {
  284. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
  285. },
  286. {
  287. location: &location{"dc1", "r2", &master_pb.DataNodeInfo{Id: "dn2"}},
  288. },
  289. },
  290. expected: true,
  291. },
  292. {
  293. name: "test 010",
  294. replication: "010",
  295. replicas: []*VolumeReplica{
  296. {
  297. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
  298. },
  299. {
  300. location: &location{"dc1", "r2", &master_pb.DataNodeInfo{Id: "dn2"}},
  301. },
  302. },
  303. expected: false,
  304. },
  305. {
  306. name: "test 011",
  307. replication: "011",
  308. replicas: []*VolumeReplica{
  309. {
  310. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
  311. },
  312. {
  313. location: &location{"dc1", "r2", &master_pb.DataNodeInfo{Id: "dn2"}},
  314. },
  315. },
  316. expected: false,
  317. },
  318. {
  319. name: "test 110",
  320. replication: "110",
  321. replicas: []*VolumeReplica{
  322. {
  323. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
  324. },
  325. {
  326. location: &location{"dc1", "r2", &master_pb.DataNodeInfo{Id: "dn2"}},
  327. },
  328. },
  329. expected: false,
  330. },
  331. {
  332. name: "test 100",
  333. replication: "100",
  334. replicas: []*VolumeReplica{
  335. {
  336. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
  337. },
  338. {
  339. location: &location{"dc1", "r2", &master_pb.DataNodeInfo{Id: "dn2"}},
  340. },
  341. },
  342. expected: true,
  343. },
  344. }
  345. for _, tt := range tests {
  346. replicaPlacement, _ := super_block.NewReplicaPlacementFromString(tt.replication)
  347. println("replication:", tt.replication, "expected", tt.expected, "name:", tt.name)
  348. if isMisplaced(tt.replicas, replicaPlacement) != tt.expected {
  349. t.Errorf("%s: expect %v %v %+v",
  350. tt.name, tt.expected, tt.replication, tt.replicas)
  351. }
  352. }
  353. }
  354. func TestPickingMisplacedVolumeToDelete(t *testing.T) {
  355. var tests = []testcase{
  356. {
  357. name: "test 001",
  358. replication: "001",
  359. replicas: []*VolumeReplica{
  360. {
  361. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
  362. info: &master_pb.VolumeInformationMessage{
  363. Size: 100,
  364. },
  365. },
  366. {
  367. location: &location{"dc1", "r2", &master_pb.DataNodeInfo{Id: "dn2"}},
  368. info: &master_pb.VolumeInformationMessage{
  369. Size: 99,
  370. },
  371. },
  372. },
  373. possibleLocation: location{"dc1", "r2", &master_pb.DataNodeInfo{Id: "dn2"}},
  374. },
  375. {
  376. name: "test 100",
  377. replication: "100",
  378. replicas: []*VolumeReplica{
  379. {
  380. location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
  381. info: &master_pb.VolumeInformationMessage{
  382. Size: 100,
  383. },
  384. },
  385. {
  386. location: &location{"dc1", "r2", &master_pb.DataNodeInfo{Id: "dn2"}},
  387. info: &master_pb.VolumeInformationMessage{
  388. Size: 99,
  389. },
  390. },
  391. },
  392. possibleLocation: location{"dc1", "r2", &master_pb.DataNodeInfo{Id: "dn2"}},
  393. },
  394. }
  395. for _, tt := range tests {
  396. replicaPlacement, _ := super_block.NewReplicaPlacementFromString(tt.replication)
  397. println("replication:", tt.replication, "name:", tt.name)
  398. if x := pickOneMisplacedVolume(tt.replicas, replicaPlacement); x.location.dataNode.Id != tt.possibleLocation.dataNode.Id {
  399. t.Errorf("%s: picked %+v for replication %v",
  400. tt.name, x.location.dataNode.Id, tt.replication)
  401. } else {
  402. t.Logf("%s: picked %+v %v",
  403. tt.name, x.location.dataNode.Id, tt.replication)
  404. }
  405. }
  406. }