cubefs

Форк
0
/
multi_ver_test.go 
1612 строк · 50.7 Кб
1
// Copyright 2023 The CubeFS Authors.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12
// implied. See the License for the specific language governing
13
// permissions and limitations under the License.
14

15
package metanode
16

17
import (
18
	"encoding/json"
19
	"fmt"
20
	"math"
21
	"os"
22
	"reflect"
23
	"sort"
24
	"sync"
25
	"testing"
26
	"time"
27

28
	raftstoremock "github.com/cubefs/cubefs/metanode/mocktest/raftstore"
29
	"github.com/cubefs/cubefs/proto"
30
	"github.com/cubefs/cubefs/util"
31
	"github.com/cubefs/cubefs/util/config"
32
	"github.com/cubefs/cubefs/util/log"
33
	"github.com/golang/mock/gomock"
34
	"github.com/stretchr/testify/assert"
35
)
36

37
var (
38
	partitionId uint64 = 10
39
	manager            = &metadataManager{partitions: make(map[uint64]MetaPartition), volUpdating: new(sync.Map)}
40
	mp          *metaPartition
41
)
42

43
// PartitionId   uint64              `json:"partition_id"`
44
// VolName       string              `json:"vol_name"`
45
// PartitionType int                 `json:"partition_type"`
46
var metaConf = &MetaPartitionConfig{
47
	PartitionId:   10001,
48
	VolName:       VolNameForTest,
49
	PartitionType: proto.VolumeTypeHot,
50
}
51

52
const (
53
	ConfigKeyLogDir          = "logDir"
54
	ConfigKeyLogLevel        = "logLevel"
55
	DirModeType       uint32 = 2147484141
56
)
57

58
var cfgJSON = `{
59
		"role": "meta",
60
		"logDir": "/tmp/cubefs/Logs",
61
		"logLevel":"debug",
62
		"walDir":"/tmp/cubefs/raft",
63
		"clusterName":"cubefs"
64
	}`
65
var tlog *testing.T
66

67
func tLogf(format string, args ...interface{}) {
68
	tlog.Log(fmt.Sprintf(format, args...))
69
}
70

71
func newPartition(conf *MetaPartitionConfig, manager *metadataManager) (mp *metaPartition) {
72
	mp = &metaPartition{
73
		config:        conf,
74
		dentryTree:    NewBtree(),
75
		inodeTree:     NewBtree(),
76
		extendTree:    NewBtree(),
77
		multipartTree: NewBtree(),
78
		stopC:         make(chan bool),
79
		storeChan:     make(chan *storeMsg, 100),
80
		freeList:      newFreeList(),
81
		extDelCh:      make(chan []proto.ExtentKey, defaultDelExtentsCnt),
82
		extReset:      make(chan struct{}),
83
		vol:           NewVol(),
84
		manager:       manager,
85
		verSeq:        conf.VerSeq,
86
	}
87
	mp.config.Cursor = 0
88
	mp.config.End = 100000
89
	mp.uidManager = NewUidMgr(conf.VolName, mp.config.PartitionId)
90
	mp.mqMgr = NewQuotaManager(conf.VolName, mp.config.PartitionId)
91
	return mp
92
}
93

94
func init() {
95
	cfg := config.LoadConfigString(cfgJSON)
96

97
	logDir := cfg.GetString(ConfigKeyLogDir)
98
	os.RemoveAll(logDir)
99

100
	if _, err := log.InitLog(logDir, "metanode", log.DebugLevel, nil, log.DefaultLogLeftSpaceLimit); err != nil {
101
		fmt.Println("Fatal: failed to start the cubefs daemon - ", err)
102
		return
103
	}
104
	log.LogDebugf("action start")
105
	return
106
}
107

108
func initMp(t *testing.T) {
109
	tlog = t
110
	mp = newPartition(metaConf, manager)
111
	mp.multiVersionList = &proto.VolVersionInfoList{}
112
	ino := testCreateInode(nil, DirModeType)
113
	t.Logf("cursor %v create ino[%v]", mp.config.Cursor, ino)
114
	mp.config.Cursor = 1000
115
}
116

117
func buildExtentKey(seq uint64, foffset uint64, extid uint64, exteoffset uint64, size uint32) proto.ExtentKey {
118
	return proto.ExtentKey{
119
		FileOffset:   foffset,
120
		PartitionId:  partitionId,
121
		ExtentId:     extid,
122
		ExtentOffset: exteoffset, // offset in extent like tiny extent offset large than 0,normal is 0
123
		Size:         size,       // extent real size?
124
		SnapInfo: &proto.ExtSnapInfo{
125
			VerSeq: seq,
126
		},
127
	}
128
}
129

130
func buildExtents(verSeq uint64, startFileOff uint64, extid uint64) (exts []proto.ExtentKey) {
131
	var (
132
		i      uint64
133
		extOff uint64 = 0
134
	)
135
	for ; i < 1; i++ {
136
		ext1 := buildExtentKey(verSeq, startFileOff+i*1000, extid, extOff+i*1000, 1000)
137
		exts = append(exts, ext1)
138
	}
139

140
	return
141
}
142

143
func isExtEqual(ek1 proto.ExtentKey, ek2 proto.ExtentKey) bool {
144
	return ek1.ExtentId == ek2.ExtentId &&
145
		ek1.FileOffset == ek2.FileOffset &&
146
		ek1.Size == ek2.Size &&
147
		ek1.ExtentOffset == ek2.ExtentOffset &&
148
		ek1.PartitionId == ek2.PartitionId
149
}
150

151
func isDentryEqual(den1 *proto.Dentry, den2 *Dentry) bool {
152
	return den1.Inode == den2.Inode &&
153
		den1.Name == den2.Name &&
154
		den1.Type == den2.Type
155
}
156

157
func checkOffSetInSequnce(t *testing.T, eks []proto.ExtentKey) bool {
158
	if len(eks) < 2 {
159
		return true
160
	}
161

162
	var (
163
		lastFileOff uint64 = eks[0].FileOffset
164
		lastSize    uint32 = eks[0].Size
165
	)
166

167
	for idx, ext := range eks[1:] {
168
		// t.Logf("idx:%v ext:%v, lastFileOff %v, lastSize %v", idx, ext, lastFileOff, lastSize)
169
		if ext.FileOffset != lastFileOff+uint64(lastSize) {
170
			t.Errorf("checkOffSetInSequnce not equal idx %v %v:(%v+%v) eks{%v}", idx, ext.FileOffset, lastFileOff, lastSize, eks)
171
			return false
172
		}
173
		lastFileOff = ext.FileOffset
174
		lastSize = ext.Size
175
	}
176
	return true
177
}
178

179
func testGetExtList(t *testing.T, ino *Inode, verRead uint64) (resp *proto.GetExtentsResponse) {
180
	reqExtList := &proto.GetExtentsRequest{
181
		VolName:     metaConf.VolName,
182
		PartitionID: partitionId,
183
		Inode:       ino.Inode,
184
	}
185
	packet := &Packet{}
186
	reqExtList.VerSeq = verRead
187
	assert.True(t, nil == mp.ExtentsList(reqExtList, packet))
188
	resp = &proto.GetExtentsResponse{}
189

190
	assert.True(t, nil == packet.UnmarshalData(resp))
191
	t.Logf("testGetExtList.resp %v", resp)
192
	assert.True(t, packet.ResultCode == proto.OpOk)
193
	assert.True(t, checkOffSetInSequnce(t, resp.Extents))
194
	return
195
}
196

197
func testCheckExtList(t *testing.T, ino *Inode, seqArr []uint64) bool {
198
	reqExtList := &proto.GetExtentsRequest{
199
		VolName:     metaConf.VolName,
200
		PartitionID: partitionId,
201
		Inode:       ino.Inode,
202
	}
203

204
	for idx, verRead := range seqArr {
205
		t.Logf("check extlist index %v ver [%v]", idx, verRead)
206
		reqExtList.VerSeq = verRead
207
		getExtRsp := testGetExtList(t, ino, verRead)
208
		t.Logf("check extlist rsp %v size %v,%v", getExtRsp, getExtRsp.Size, ino.Size)
209
		assert.True(t, getExtRsp.Size == uint64(1000*(idx+1)))
210
		if getExtRsp.Size != uint64(1000*(idx+1)) {
211
			panic(nil)
212
		}
213
	}
214
	return true
215
}
216

217
func testCreateInode(t *testing.T, mode uint32) *Inode {
218
	inoID, _ := mp.nextInodeID()
219
	if t != nil {
220
		t.Logf("inode id:%v", inoID)
221
	}
222

223
	ino := NewInode(inoID, mode)
224
	ino.setVer(mp.verSeq)
225
	if t != nil {
226
		t.Logf("testCreateInode ino[%v]", ino)
227
	}
228

229
	mp.fsmCreateInode(ino)
230
	return ino
231
}
232

233
func testCreateDentry(t *testing.T, parentId uint64, inodeId uint64, name string, mod uint32) *Dentry {
234
	dentry := &Dentry{
235
		ParentId:  parentId,
236
		Name:      name,
237
		Inode:     inodeId,
238
		Type:      mod,
239
		multiSnap: NewDentrySnap(mp.verSeq),
240
	}
241

242
	t.Logf("createDentry dentry %v", dentry)
243
	ret := mp.fsmCreateDentry(dentry, false)
244
	assert.True(t, proto.OpOk == ret)
245
	if ret != proto.OpOk {
246
		panic(nil)
247
	}
248
	return dentry
249
}
250

251
func TestEkMarshal(t *testing.T) {
252
	log.LogDebugf("TestEkMarshal")
253
	initMp(t)
254
	// inodeID uint64, ekRef *sync.Map, ek *proto.ExtentKey
255
	ino := testCreateInode(t, FileModeType)
256
	ino.multiSnap = NewMultiSnap(mp.verSeq)
257
	ino.multiSnap.ekRefMap = new(sync.Map)
258
	ek := &proto.ExtentKey{
259
		PartitionId: 10,
260
		ExtentId:    20,
261
		SnapInfo: &proto.ExtSnapInfo{
262
			VerSeq: 123444,
263
		},
264
	}
265
	id := storeEkSplit(0, 0, ino.multiSnap.ekRefMap, ek)
266
	dpID, extID := proto.ParseFromId(id)
267
	assert.True(t, dpID == ek.PartitionId)
268
	assert.True(t, extID == ek.ExtentId)
269

270
	ok, _ := ino.DecSplitEk(mp.config.PartitionId, ek)
271
	assert.True(t, ok == true)
272
	log.LogDebugf("TestEkMarshal close")
273
}
274

275
func initVer() {
276
	verInfo := &proto.VolVersionInfo{
277
		Ver:    0,
278
		Status: proto.VersionNormal,
279
	}
280
	mp.multiVersionList.VerList = append(mp.multiVersionList.VerList, verInfo)
281
}
282

283
func testGetSplitSize(t *testing.T, ino *Inode) (cnt int32) {
284
	if nil == mp.inodeTree.Get(ino) {
285
		return
286
	}
287
	ino.multiSnap.ekRefMap.Range(func(key, value interface{}) bool {
288
		dpID, extID := proto.ParseFromId(key.(uint64))
289
		log.LogDebugf("id:[%v],key %v (dpId-%v|extId-%v) refCnt %v", cnt, key, dpID, extID, value.(uint32))
290
		cnt++
291
		return true
292
	})
293
	return
294
}
295

296
func testGetEkRefCnt(t *testing.T, ino *Inode, ek *proto.ExtentKey) (cnt uint32) {
297
	id := ek.GenerateId()
298
	var (
299
		val interface{}
300
		ok  bool
301
	)
302
	if nil == mp.inodeTree.Get(ino) {
303
		t.Logf("testGetEkRefCnt inode[%v] ek [%v] not found", ino, ek)
304
		return
305
	}
306
	if val, ok = ino.multiSnap.ekRefMap.Load(id); !ok {
307
		t.Logf("inode[%v] not ek [%v]", ino.Inode, ek)
308
		return
309
	}
310
	t.Logf("testGetEkRefCnt ek [%v] get refCnt %v", ek, val.(uint32))
311
	return val.(uint32)
312
}
313

314
func testDelDiscardEK(t *testing.T, fileIno *Inode) (cnt uint32) {
315
	delCnt := len(mp.extDelCh)
316
	t.Logf("enter testDelDiscardEK extDelCh size %v", delCnt)
317
	if len(mp.extDelCh) == 0 {
318
		t.Logf("testDelDiscardEK discard ek cnt %v", cnt)
319
		return
320
	}
321
	for i := 0; i < delCnt; i++ {
322
		eks := <-mp.extDelCh
323
		for _, ek := range eks {
324
			t.Logf("the delete ek is %v", ek)
325
			cnt++
326
		}
327
		t.Logf("pop [%v]", i)
328
	}
329
	t.Logf("testDelDiscardEK discard ek cnt %v", cnt)
330
	return
331
}
332

333
// create
334
func TestSplitKeyDeletion(t *testing.T) {
335
	log.LogDebugf("action[TestSplitKeyDeletion] start!!!!!!!!!!!")
336
	initMp(t)
337
	initVer()
338
	mp.config.Cursor = 1100
339

340
	fileIno := testCreateInode(t, FileModeType)
341

342
	fileName := "fileTest"
343
	dirDen := testCreateDentry(t, 1, fileIno.Inode, fileName, FileModeType)
344
	assert.True(t, dirDen != nil)
345

346
	initExt := buildExtentKey(0, 0, 1024, 0, 1000)
347
	fileIno.Extents.eks = append(fileIno.Extents.eks, initExt)
348

349
	splitSeq := testCreateVer()
350
	splitKey := buildExtentKey(splitSeq, 500, 1024, 128100, 100)
351
	extents := &SortedExtents{}
352
	extents.eks = append(extents.eks, splitKey)
353

354
	iTmp := &Inode{
355
		Inode:   fileIno.Inode,
356
		Extents: extents,
357
		multiSnap: &InodeMultiSnap{
358
			verSeq: splitSeq,
359
		},
360
	}
361
	mp.verSeq = iTmp.getVer()
362
	mp.fsmAppendExtentsWithCheck(iTmp, true)
363
	assert.True(t, testGetSplitSize(t, fileIno) == 1)
364
	assert.True(t, testGetEkRefCnt(t, fileIno, &initExt) == 4)
365

366
	testCleanSnapshot(t, 0)
367
	delCnt := testDelDiscardEK(t, fileIno)
368
	assert.True(t, 1 == delCnt)
369

370
	assert.True(t, testGetSplitSize(t, fileIno) == 1)
371
	assert.True(t, testGetEkRefCnt(t, fileIno, &initExt) == 3)
372

373
	log.LogDebugf("try to deletion current")
374
	testDeleteDirTree(t, 1, 0)
375

376
	fileIno.GetAllExtsOfflineInode(mp.config.PartitionId)
377

378
	splitCnt := uint32(testGetSplitSize(t, fileIno))
379
	assert.True(t, 0 == splitCnt)
380

381
	assert.True(t, testGetSplitSize(t, fileIno) == 0)
382
	assert.True(t, testGetEkRefCnt(t, fileIno, &initExt) == 0)
383
}
384

385
func testGetlastVer() (verSeq uint64) {
386
	vlen := len(mp.multiVersionList.VerList)
387
	return mp.multiVersionList.VerList[vlen-1].Ver
388
}
389

390
var tm = time.Now().Unix()
391

392
func testCreateVer() (verSeq uint64) {
393
	mp.multiVersionList.RWLock.Lock()
394
	defer mp.multiVersionList.RWLock.Unlock()
395

396
	tm = tm + 1
397
	verInfo := &proto.VolVersionInfo{
398
		Ver:    uint64(tm),
399
		Status: proto.VersionNormal,
400
	}
401
	mp.multiVersionList.VerList = append(mp.multiVersionList.VerList, verInfo)
402
	mp.verSeq = verInfo.Ver
403
	return verInfo.Ver
404
}
405

406
func testReadDirAll(t *testing.T, verSeq uint64, parentId uint64) (resp *ReadDirLimitResp) {
407
	// testPrintAllDentry(t)
408
	t.Logf("[testReadDirAll] with seq [%v] parentId %v", verSeq, parentId)
409
	req := &ReadDirLimitReq{
410
		PartitionID: partitionId,
411
		VolName:     mp.GetVolName(),
412
		ParentID:    parentId,
413
		Limit:       math.MaxUint64,
414
		VerSeq:      verSeq,
415
	}
416
	return mp.readDirLimit(req)
417
}
418

419
func testVerListRemoveVer(t *testing.T, verSeq uint64) bool {
420
	testPrintAllSysVerList(t)
421
	for i, ver := range mp.multiVersionList.VerList {
422
		if ver.Ver == verSeq {
423
			// mp.multiVersionList = append(mp.multiVersionList[:i], mp.multiVersionList[i+1:]...)
424
			if i == len(mp.multiVersionList.VerList)-1 {
425
				mp.multiVersionList.VerList = mp.multiVersionList.VerList[:i]
426
				return true
427
			}
428
			mp.multiVersionList.VerList = append(mp.multiVersionList.VerList[:i], mp.multiVersionList.VerList[i+1:]...)
429
			return true
430
		}
431
	}
432
	return false
433
}
434

435
var (
436
	ct        = uint64(time.Now().Unix())
437
	seqAllArr = []uint64{0, ct, ct + 2111, ct + 10333, ct + 53456, ct + 60000, ct + 72344, ct + 234424, ct + 334424}
438
)
439

440
func TestAppendList(t *testing.T) {
441
	initMp(t)
442
	for _, verSeq := range seqAllArr {
443
		verInfo := &proto.VolVersionInfo{
444
			Ver:    verSeq,
445
			Status: proto.VersionNormal,
446
		}
447
		mp.multiVersionList.VerList = append(mp.multiVersionList.VerList, verInfo)
448
	}
449

450
	ino := testCreateInode(t, 0)
451
	t.Logf("enter TestAppendList")
452
	index := 5
453
	seqArr := seqAllArr[1:index]
454
	t.Logf("layer len %v, arr size %v, seqarr(%v)", ino.getLayerLen(), len(seqArr), seqArr)
455
	for idx, seq := range seqArr {
456
		exts := buildExtents(seq, uint64(idx*1000), uint64(idx))
457
		t.Logf("buildExtents exts[%v]", exts)
458
		iTmp := &Inode{
459
			Inode: ino.Inode,
460
			Extents: &SortedExtents{
461
				eks: exts,
462
			},
463
			ObjExtents: NewSortedObjExtents(),
464
			multiSnap: &InodeMultiSnap{
465
				verSeq: seq,
466
			},
467
		}
468
		mp.verSeq = seq
469

470
		if status := mp.fsmAppendExtentsWithCheck(iTmp, false); status != proto.OpOk {
471
			t.Errorf("status [%v]", status)
472
		}
473
	}
474
	t.Logf("layer len %v, arr size %v, seqarr(%v)", ino.getLayerLen(), len(seqArr), seqArr)
475
	assert.True(t, ino.getLayerLen() == len(seqArr))
476
	assert.True(t, ino.getVer() == mp.verSeq)
477

478
	for i := 0; i < len(seqArr)-1; i++ {
479
		assert.True(t, ino.getLayerVer(i) == seqArr[len(seqArr)-i-2])
480
		t.Logf("layer %v len %v content %v,seq [%v], %v", i, len(ino.multiSnap.multiVersions[i].Extents.eks), ino.multiSnap.multiVersions[i].Extents.eks,
481
			ino.getLayerVer(i), seqArr[len(seqArr)-i-2])
482
		assert.True(t, len(ino.multiSnap.multiVersions[i].Extents.eks) == 0)
483
	}
484

485
	//-------------   split at begin -----------------------------------------
486
	t.Logf("start split at begin")
487
	splitSeq := seqAllArr[index]
488
	splitKey := buildExtentKey(splitSeq, 0, 0, 128000, 10)
489
	extents := &SortedExtents{}
490
	extents.eks = append(extents.eks, splitKey)
491

492
	iTmp := &Inode{
493
		Inode:   ino.Inode,
494
		Extents: extents,
495
		multiSnap: &InodeMultiSnap{
496
			verSeq: splitSeq,
497
		},
498
	}
499
	mp.verSeq = iTmp.getVer()
500
	mp.fsmAppendExtentsWithCheck(iTmp, true)
501
	t.Logf("in split at begin")
502
	assert.True(t, ino.multiSnap.multiVersions[0].Extents.eks[0].GetSeq() == ino.getLayerVer(3))
503
	assert.True(t, ino.multiSnap.multiVersions[0].Extents.eks[0].FileOffset == 0)
504
	assert.True(t, ino.multiSnap.multiVersions[0].Extents.eks[0].ExtentId == 0)
505
	assert.True(t, ino.multiSnap.multiVersions[0].Extents.eks[0].ExtentOffset == 0)
506
	assert.True(t, ino.multiSnap.multiVersions[0].Extents.eks[0].Size == splitKey.Size)
507

508
	t.Logf("in split at begin")
509

510
	assert.True(t, isExtEqual(ino.Extents.eks[0], splitKey))
511
	assert.True(t, checkOffSetInSequnce(t, ino.Extents.eks))
512

513
	t.Logf("top layer len %v, layer 1 len %v arr size %v", len(ino.Extents.eks), len(ino.multiSnap.multiVersions[0].Extents.eks), len(seqArr))
514
	assert.True(t, len(ino.multiSnap.multiVersions[0].Extents.eks) == 1)
515
	assert.True(t, len(ino.Extents.eks) == len(seqArr)+1)
516

517
	testCheckExtList(t, ino, seqArr)
518

519
	//--------  split at middle  -----------------------------------------------
520
	t.Logf("start split at middle")
521

522
	lastTopEksLen := len(ino.Extents.eks)
523
	t.Logf("split at middle lastTopEksLen %v", lastTopEksLen)
524

525
	index++
526
	splitSeq = seqAllArr[index]
527
	splitKey = buildExtentKey(splitSeq, 500, 0, 128100, 100)
528
	extents = &SortedExtents{}
529
	extents.eks = append(extents.eks, splitKey)
530

531
	iTmp = &Inode{
532
		Inode:   ino.Inode,
533
		Extents: extents,
534
		multiSnap: &InodeMultiSnap{
535
			verSeq: splitSeq,
536
		},
537
	}
538
	t.Logf("split at middle multiSnap.multiVersions %v", ino.getLayerLen())
539
	mp.verSeq = iTmp.getVer()
540
	mp.fsmAppendExtentsWithCheck(iTmp, true)
541
	t.Logf("split at middle multiSnap.multiVersions %v", ino.getLayerLen())
542

543
	getExtRsp := testGetExtList(t, ino, ino.getLayerVer(0))
544
	t.Logf("split at middle getExtRsp len %v seq(%v), toplayer len:%v seq(%v)",
545
		len(getExtRsp.Extents), ino.getLayerVer(0), len(ino.Extents.eks), ino.getVer())
546

547
	assert.True(t, len(getExtRsp.Extents) == lastTopEksLen+2)
548
	assert.True(t, len(ino.Extents.eks) == lastTopEksLen+2)
549
	assert.True(t, checkOffSetInSequnce(t, ino.Extents.eks))
550

551
	t.Logf("ino exts{%v}", ino.Extents.eks)
552

553
	//--------  split at end  -----------------------------------------------
554
	t.Logf("start split at end")
555
	// split at end
556
	lastTopEksLen = len(ino.Extents.eks)
557
	index++
558
	splitSeq = seqAllArr[index]
559
	splitKey = buildExtentKey(splitSeq, 3900, 3, 129000, 100)
560
	extents = &SortedExtents{}
561
	extents.eks = append(extents.eks, splitKey)
562

563
	iTmp = &Inode{
564
		Inode:   ino.Inode,
565
		Extents: extents,
566
		multiSnap: &InodeMultiSnap{
567
			verSeq: splitSeq,
568
		},
569
	}
570
	t.Logf("split key:%v", splitKey)
571
	getExtRsp = testGetExtList(t, ino, ino.getLayerVer(0))
572
	t.Logf("split at middle multiSnap.multiVersions %v, extent %v, level 1 %v", ino.getLayerLen(), getExtRsp.Extents, ino.multiSnap.multiVersions[0].Extents.eks)
573
	mp.verSeq = iTmp.getVer()
574
	mp.fsmAppendExtentsWithCheck(iTmp, true)
575
	t.Logf("split at middle multiSnap.multiVersions %v", ino.getLayerLen())
576
	getExtRsp = testGetExtList(t, ino, ino.getLayerVer(0))
577
	t.Logf("split at middle multiSnap.multiVersions %v, extent %v, level 1 %v", ino.getLayerLen(), getExtRsp.Extents, ino.multiSnap.multiVersions[0].Extents.eks)
578

579
	t.Logf("split at middle getExtRsp len %v seq(%v), toplayer len:%v seq(%v)",
580
		len(getExtRsp.Extents), ino.getLayerVer(0), len(ino.Extents.eks), ino.getVer())
581

582
	assert.True(t, len(getExtRsp.Extents) == lastTopEksLen+1)
583
	assert.True(t, len(ino.Extents.eks) == lastTopEksLen+1)
584
	assert.True(t, isExtEqual(ino.Extents.eks[lastTopEksLen], splitKey))
585
	// assert.True(t, false)
586

587
	//--------  split at the splited one  -----------------------------------------------
588
	t.Logf("start split at end")
589
	// split at end
590
	lastTopEksLen = len(ino.Extents.eks)
591
	index++
592
	splitSeq = seqAllArr[index]
593
	splitKey = buildExtentKey(splitSeq, 3950, 3, 129000, 20)
594
	extents = &SortedExtents{}
595
	extents.eks = append(extents.eks, splitKey)
596

597
	iTmp = &Inode{
598
		Inode:   ino.Inode,
599
		Extents: extents,
600
		multiSnap: &InodeMultiSnap{
601
			verSeq: splitSeq,
602
		},
603
	}
604
	t.Logf("split key:%v", splitKey)
605
	mp.verSeq = iTmp.getVer()
606
	mp.fsmAppendExtentsWithCheck(iTmp, true)
607

608
	getExtRsp = testGetExtList(t, ino, ino.getLayerVer(0))
609

610
	assert.True(t, len(ino.Extents.eks) == lastTopEksLen+2)
611
	assert.True(t, checkOffSetInSequnce(t, ino.Extents.eks))
612
}
613

614
//func MockSubmitTrue(mp *metaPartition, inode uint64, offset int, data []byte,
615
//	flags int) (write int, err error) {
616
//	return len(data), nil
617
//}
618

619
func testPrintAllSysVerList(t *testing.T) {
620
	for idx, info := range mp.multiVersionList.VerList {
621
		t.Logf("testPrintAllSysVerList idx %v, info %v", idx, info)
622
	}
623
}
624

625
func testPrintAllDentry(t *testing.T) uint64 {
626
	var cnt uint64
627
	mp.dentryTree.Ascend(func(i BtreeItem) bool {
628
		den := i.(*Dentry)
629
		t.Logf("testPrintAllDentry name %v top layer dentry:%v", den.Name, den)
630
		if den.getSnapListLen() > 0 {
631
			for id, info := range den.multiSnap.dentryList {
632
				t.Logf("testPrintAllDentry name %v layer %v, denseq [%v] den %v", den.Name, id, info.getVerSeq(), info)
633
			}
634
		}
635
		cnt++
636
		return true
637
	})
638
	return cnt
639
}
640

641
func testPrintAllInodeInfo(t *testing.T) {
642
	mp.inodeTree.Ascend(func(item BtreeItem) bool {
643
		i := item.(*Inode)
644
		t.Logf("action[PrintAllVersionInfo] toplayer inode[%v] verSeq [%v] hist len [%v]", i, i.getVer(), i.getLayerLen())
645
		if i.getLayerLen() == 0 {
646
			return true
647
		}
648
		for id, info := range i.multiSnap.multiVersions {
649
			t.Logf("action[PrintAllVersionInfo] layer [%v]  verSeq [%v] inode[%v]", id, info.getVer(), info)
650
		}
651
		return true
652
	})
653
}
654

655
func testPrintInodeInfo(t *testing.T, ino *Inode) {
656
	i := mp.inodeTree.Get(ino).(*Inode)
657
	t.Logf("action[PrintAllVersionInfo] toplayer inode[%v] verSeq [%v] hist len [%v]", i, i.getVer(), i.getLayerLen())
658
	if i.getLayerLen() == 0 {
659
		return
660
	}
661
	for id, info := range i.multiSnap.multiVersions {
662
		t.Logf("action[PrintAllVersionInfo] layer [%v]  verSeq [%v] inode[%v]", id, info.getVer(), info)
663
	}
664
}
665

666
func testDelDirSnapshotVersion(t *testing.T, verSeq uint64, dirIno *Inode, dirDentry *Dentry) {
667
	if verSeq != 0 {
668
		assert.True(t, testVerListRemoveVer(t, verSeq))
669
	}
670

671
	rspReadDir := testReadDirAll(t, verSeq, dirIno.Inode)
672
	// testPrintAllDentry(t)
673

674
	rDirIno := dirIno.Copy().(*Inode)
675
	rDirIno.setVerNoCheck(verSeq)
676

677
	rspDelIno := mp.fsmUnlinkInode(rDirIno, 0)
678

679
	t.Logf("rspDelinfo ret %v content %v", rspDelIno.Status, rspDelIno)
680
	assert.True(t, rspDelIno.Status == proto.OpOk)
681
	if rspDelIno.Status != proto.OpOk {
682
		return
683
	}
684
	rDirDentry := dirDentry.Copy().(*Dentry)
685
	rDirDentry.setVerSeq(verSeq)
686
	rspDelDen := mp.fsmDeleteDentry(rDirDentry, false)
687
	assert.True(t, rspDelDen.Status == proto.OpOk)
688

689
	for idx, info := range rspReadDir.Children {
690
		t.Logf("testDelDirSnapshotVersion: delseq [%v]  to del idx %v infof %v", verSeq, idx, info)
691
		rino := &Inode{
692
			Inode: info.Inode,
693
			Type:  FileModeType,
694
			multiSnap: &InodeMultiSnap{
695
				verSeq: verSeq,
696
			},
697
		}
698
		testPrintInodeInfo(t, rino)
699
		log.LogDebugf("testDelDirSnapshotVersion get rino[%v] start", rino)
700
		t.Logf("testDelDirSnapshotVersion get rino[%v] start", rino)
701
		ino := mp.getInode(rino, false)
702
		log.LogDebugf("testDelDirSnapshotVersion get rino[%v] end", ino)
703
		t.Logf("testDelDirSnapshotVersion get rino[%v] end", rino)
704
		assert.True(t, ino.Status == proto.OpOk)
705
		if ino.Status != proto.OpOk {
706
			panic(nil)
707
		}
708
		rino.setVer(verSeq)
709
		rspDelIno = mp.fsmUnlinkInode(rino, 0)
710

711
		assert.True(t, rspDelIno.Status == proto.OpOk || rspDelIno.Status == proto.OpNotExistErr)
712
		if rspDelIno.Status != proto.OpOk && rspDelIno.Status != proto.OpNotExistErr {
713
			t.Logf("testDelDirSnapshotVersion: rspDelino[%v] return st %v", rspDelIno, proto.ParseErrorCode(int32(rspDelIno.Status)))
714
			panic(nil)
715
		}
716
		dentry := &Dentry{
717
			ParentId:  rDirIno.Inode,
718
			Name:      info.Name,
719
			Type:      FileModeType,
720
			multiSnap: NewDentrySnap(verSeq),
721
			Inode:     rino.Inode,
722
		}
723
		log.LogDebugf("test.testDelDirSnapshotVersion: dentry param %v ", dentry)
724
		// testPrintAllDentry(t)
725
		iden, st := mp.getDentry(dentry)
726
		if st != proto.OpOk {
727
			t.Logf("testDelDirSnapshotVersion: dentry %v return st %v", dentry, proto.ParseErrorCode(int32(st)))
728
		}
729
		log.LogDebugf("test.testDelDirSnapshotVersion: get dentry %v ", iden)
730
		assert.True(t, st == proto.OpOk)
731

732
		rDen := iden.Copy().(*Dentry)
733
		rDen.multiSnap = NewDentrySnap(verSeq)
734
		rspDelDen = mp.fsmDeleteDentry(rDen, false)
735
		assert.True(t, rspDelDen.Status == proto.OpOk)
736
	}
737
}
738

739
func TestDentry(t *testing.T) {
740
	initMp(t)
741

742
	var denArry []*Dentry
743
	// err := gohook.HookMethod(mp, "submit", MockSubmitTrue, nil)
744
	mp.config.Cursor = 1100
745
	//--------------------build dir and it's child on different version ------------------
746
	seq0 := testCreateVer()
747
	dirIno := testCreateInode(t, DirModeType)
748
	assert.True(t, dirIno != nil)
749
	dirDen := testCreateDentry(t, 1, dirIno.Inode, "testDir", DirModeType)
750
	assert.True(t, dirDen != nil)
751

752
	fIno := testCreateInode(t, FileModeType)
753
	assert.True(t, fIno != nil)
754
	fDen := testCreateDentry(t, dirIno.Inode, fIno.Inode, "testfile", FileModeType)
755
	denArry = append(denArry, fDen)
756

757
	//--------------------------------------
758
	seq1 := testCreateVer()
759
	fIno1 := testCreateInode(t, FileModeType)
760
	fDen1 := testCreateDentry(t, dirIno.Inode, fIno1.Inode, "testfile2", FileModeType)
761
	denArry = append(denArry, fDen1)
762

763
	//--------------------------------------
764
	seq2 := testCreateVer()
765
	fIno2 := testCreateInode(t, FileModeType)
766
	fDen2 := testCreateDentry(t, dirIno.Inode, fIno2.Inode, "testfile3", FileModeType)
767
	denArry = append(denArry, fDen2)
768

769
	//--------------------------------------
770
	seq3 := testCreateVer()
771
	//--------------------read dir and it's child on different version ------------------
772

773
	t.Logf("TestDentry seq [%v],%v,uncommit %v,dir:%v, dentry {%v],inode[%v,%v,%v]", seq1, seq2, seq3, dirDen, denArry, fIno, fIno1, fIno2)
774
	//-----------read curr version --
775
	rspReadDir := testReadDirAll(t, 0, 1)
776
	t.Logf("len child %v, len arry %v", len(rspReadDir.Children), len(denArry))
777
	assert.True(t, len(rspReadDir.Children) == 1)
778
	assert.True(t, isDentryEqual(&rspReadDir.Children[0], dirDen))
779

780
	rspReadDir = testReadDirAll(t, 0, dirIno.Inode)
781
	assert.True(t, len(rspReadDir.Children) == len(denArry))
782

783
	for idx, info := range rspReadDir.Children {
784
		t.Logf("getinfo:%v, expect:%v", info, denArry[idx])
785
		assert.True(t, isDentryEqual(&info, denArry[idx]))
786
	}
787

788
	//-----------read 0 version --
789
	rspReadDir = testReadDirAll(t, math.MaxUint64, dirIno.Inode)
790
	assert.True(t, len(rspReadDir.Children) == 0)
791

792
	//-----------read layer 1 version --   seq2 is the last layer, seq1 is the second layer
793
	rspReadDir = testReadDirAll(t, seq1, dirIno.Inode)
794
	assert.True(t, len(rspReadDir.Children) == 2)
795
	for idx, info := range rspReadDir.Children {
796
		t.Logf("getinfo:%v, expect:%v", info, denArry[idx])
797
		assert.True(t, isDentryEqual(&info, denArry[idx]))
798
	}
799
	//-----------read layer 2 version --
800
	rspReadDir = testReadDirAll(t, seq0, dirIno.Inode)
801
	assert.True(t, len(rspReadDir.Children) == 1)
802
	assert.True(t, isDentryEqual(&rspReadDir.Children[0], fDen))
803

804
	testPrintAllDentry(t)
805
	//--------------------del snapshot and read dir and it's child on different version(cann't be work on interfrace) ------------------
806
	t.Logf("try testDelDirSnapshotVersion %v", seq0)
807
	log.LogDebugf("try testDelDirSnapshotVersion %v", seq0)
808

809
	testDelDirSnapshotVersion(t, seq0, dirIno, dirDen)
810
	rspReadDir = testReadDirAll(t, seq0, dirIno.Inode)
811
	assert.True(t, len(rspReadDir.Children) == 0)
812

813
	testPrintAllDentry(t)
814
	//---------------------------------------------
815
	t.Logf("try testDelDirSnapshotVersion 0 top layer")
816
	log.LogDebugf("try testDelDirSnapshotVersion 0")
817
	testDelDirSnapshotVersion(t, 0, dirIno, dirDen)
818
	rspReadDir = testReadDirAll(t, 0, dirIno.Inode)
819
	t.Logf("after  testDelDirSnapshotVersion read seq [%v] can see file %v %v", 0, len(rspReadDir.Children), rspReadDir.Children)
820
	assert.True(t, len(rspReadDir.Children) == 0)
821
	rspReadDir = testReadDirAll(t, seq1, dirIno.Inode)
822
	t.Logf("after  testDelDirSnapshotVersion read seq [%v] can see file %v %v", seq1, len(rspReadDir.Children), rspReadDir.Children)
823
	assert.True(t, len(rspReadDir.Children) == 2)
824

825
	//---------------------------------------------
826
	t.Logf("try testDelDirSnapshotVersion %v", seq1)
827
	log.LogDebugf("try testDelDirSnapshotVersion %v", seq1)
828
	testDelDirSnapshotVersion(t, seq1, dirIno, dirDen)
829

830
	rspReadDir = testReadDirAll(t, seq1, dirIno.Inode)
831
	t.Logf("after  testDelDirSnapshotVersion %v can see file %v %v", seq1, len(rspReadDir.Children), rspReadDir.Children)
832
	assert.True(t, len(rspReadDir.Children) == 0)
833
	testPrintAllSysVerList(t)
834

835
	//---------------------------------------------
836
	t.Logf("try testDelDirSnapshotVersion %v", seq2)
837
	log.LogDebugf("try testDelDirSnapshotVersion %v", seq2)
838
	testDelDirSnapshotVersion(t, seq2, dirIno, dirDen)
839

840
	rspReadDir = testReadDirAll(t, seq2, dirIno.Inode)
841
	t.Logf("after  testDelDirSnapshotVersion %v can see file %v %v", seq1, len(rspReadDir.Children), rspReadDir.Children)
842
	assert.True(t, len(rspReadDir.Children) == 0)
843

844
	t.Logf("testPrintAllSysVerList")
845
	testPrintAllSysVerList(t)
846
	t.Logf("testPrintAllInodeInfo")
847
	testPrintAllInodeInfo(t)
848
}
849

850
func testPrintDirTree(t *testing.T, parentId uint64, path string, verSeq uint64) (dirCnt int, fCnt int) {
851
	if verSeq == 0 {
852
		verSeq = math.MaxUint64
853
	}
854
	rspReadDir := testReadDirAll(t, verSeq, parentId)
855
	for _, child := range rspReadDir.Children {
856
		pathInner := fmt.Sprintf("%v/%v", path, child.Name)
857
		if proto.IsDir(child.Type) {
858
			dirCnt++
859
			dc, fc := testPrintDirTree(t, child.Inode, pathInner, verSeq)
860
			dirCnt += dc
861
			fCnt += fc
862
			t.Logf("dir:%v", pathInner)
863
		} else {
864
			fCnt++
865
			t.Logf("file:%v", pathInner)
866
		}
867
	}
868
	return
869
}
870

871
func testAppendExt(t *testing.T, seq uint64, idx int, inode uint64) {
872
	exts := buildExtents(seq, uint64(idx*1000), uint64(idx))
873
	t.Logf("buildExtents exts[%v]", exts)
874
	iTmp := &Inode{
875
		Inode: inode,
876
		Extents: &SortedExtents{
877
			eks: exts,
878
		},
879
		ObjExtents: NewSortedObjExtents(),
880
		multiSnap: &InodeMultiSnap{
881
			verSeq: seq,
882
		},
883
	}
884
	mp.verSeq = seq
885
	if status := mp.fsmAppendExtentsWithCheck(iTmp, false); status != proto.OpOk {
886
		t.Errorf("status [%v]", status)
887
	}
888
}
889

890
func TestTruncateAndDel(t *testing.T) {
891
	log.LogDebugf("TestTruncate start")
892
	initMp(t)
893
	mp.config.Cursor = 1100
894
	//--------------------build dir and it's child on different version ------------------
895
	initVer()
896
	fileIno := testCreateInode(t, FileModeType)
897
	assert.True(t, fileIno != nil)
898
	dirDen := testCreateDentry(t, 1, fileIno.Inode, "testDir", FileModeType)
899
	assert.True(t, dirDen != nil)
900
	log.LogDebugf("TestTruncate start")
901
	testAppendExt(t, 0, 0, fileIno.Inode)
902
	log.LogDebugf("TestTruncate start")
903
	seq1 := testCreateVer() // seq1 is NOT commited
904

905
	seq2 := testCreateVer() // seq1 is commited,seq2 not commited
906

907
	t.Logf("TestTruncate. create new snapshot seq [%v],%v,file verlist [%v]", seq1, seq2, fileIno.getLayerLen())
908
	log.LogDebugf("TestTruncate start")
909
	ino := &Inode{
910
		Inode:      fileIno.Inode,
911
		Size:       500,
912
		ModifyTime: time.Now().Unix(),
913
	}
914
	mp.fsmExtentsTruncate(ino)
915
	log.LogDebugf("TestTruncate start")
916
	t.Logf("TestTruncate. create new snapshot seq [%v],%v,file verlist size %v [%v]", seq1, seq2, len(fileIno.multiSnap.multiVersions), fileIno.multiSnap.multiVersions)
917

918
	assert.True(t, 2 == len(fileIno.multiSnap.multiVersions))
919
	rsp := testGetExtList(t, fileIno, 0)
920
	assert.True(t, rsp.Size == 500)
921

922
	rsp = testGetExtList(t, fileIno, seq2)
923
	assert.True(t, rsp.Size == 500)
924

925
	rsp = testGetExtList(t, fileIno, seq1)
926
	assert.True(t, rsp.Size == 1000)
927

928
	rsp = testGetExtList(t, fileIno, math.MaxUint64)
929
	assert.True(t, rsp.Size == 1000)
930

931
	// -------------------------------------------------------
932
	log.LogDebugf("TestTruncate start")
933
	testCreateVer() // seq2 IS commited, seq3 not
934
	mp.fsmUnlinkInode(ino, 0)
935

936
	log.LogDebugf("TestTruncate start")
937
	assert.True(t, 3 == len(fileIno.multiSnap.multiVersions))
938
	rsp = testGetExtList(t, fileIno, 0)
939
	assert.True(t, len(rsp.Extents) == 0)
940

941
	rsp = testGetExtList(t, fileIno, seq2)
942
	assert.True(t, rsp.Size == 500)
943

944
	rsp = testGetExtList(t, fileIno, seq1)
945
	assert.True(t, rsp.Size == 1000)
946

947
	rsp = testGetExtList(t, fileIno, math.MaxUint64)
948
	assert.True(t, rsp.Size == 1000)
949
}
950

951
func testDeleteFile(t *testing.T, verSeq uint64, parentId uint64, child *proto.Dentry) {
952
	t.Logf("testDeleteFile seq [%v]", verSeq)
953
	fsmDentry := &Dentry{
954
		ParentId:  parentId,
955
		Name:      child.Name,
956
		Inode:     child.Inode,
957
		Type:      child.Type,
958
		multiSnap: NewDentrySnap(verSeq),
959
	}
960
	t.Logf("testDeleteFile seq [%v] %v dentry %v", verSeq, fsmDentry.getSeqFiled(), fsmDentry)
961
	assert.True(t, nil != mp.fsmDeleteDentry(fsmDentry, false))
962

963
	rino := &Inode{
964
		Inode: child.Inode,
965
		Type:  child.Type,
966
		multiSnap: &InodeMultiSnap{
967
			verSeq: verSeq,
968
		},
969
	}
970
	rino.setVer(verSeq)
971
	rspDelIno := mp.fsmUnlinkInode(rino, 0)
972

973
	assert.True(t, rspDelIno.Status == proto.OpOk || rspDelIno.Status == proto.OpNotExistErr)
974
	if rspDelIno.Status != proto.OpOk && rspDelIno.Status != proto.OpNotExistErr {
975
		t.Logf("testDelDirSnapshotVersion: rspDelino[%v] return st %v", rspDelIno, proto.ParseErrorCode(int32(rspDelIno.Status)))
976
		panic(nil)
977
	}
978
}
979

980
func testDeleteDirTree(t *testing.T, parentId uint64, verSeq uint64) {
981
	t.Logf("testDeleteDirTree parentId %v seq [%v]", parentId, verSeq)
982
	rspReadDir := testReadDirAll(t, verSeq, parentId)
983
	for _, child := range rspReadDir.Children {
984
		if proto.IsDir(child.Type) {
985
			testDeleteDirTree(t, child.Inode, verSeq)
986
		}
987
		t.Logf("action[testDeleteDirTree] delete children %v", child)
988
		log.LogDebugf("action[testDeleteDirTree] seq [%v] delete children %v", verSeq, child)
989
		testDeleteFile(t, verSeq, parentId, &child)
990
	}
991
	return
992
}
993

994
func testCleanSnapshot(t *testing.T, verSeq uint64) {
995
	t.Logf("action[testCleanSnapshot] verseq [%v]", verSeq)
996
	log.LogDebugf("action[testCleanSnapshot] verseq [%v]", verSeq)
997
	assert.True(t, testVerListRemoveVer(t, verSeq))
998
	if verSeq == 0 {
999
		verSeq = math.MaxUint64
1000
	}
1001
	testDeleteDirTree(t, 1, verSeq)
1002
	return
1003
}
1004

1005
// create
1006
func testSnapshotDeletion(t *testing.T, topFirst bool) {
1007
	log.LogDebugf("action[TestSnapshotDeletion] start!!!!!!!!!!!")
1008
	initMp(t)
1009
	initVer()
1010
	// err := gohook.HookMethod(mp, "submit", MockSubmitTrue, nil)
1011
	mp.config.Cursor = 1100
1012
	//--------------------build dir and it's child on different version ------------------
1013

1014
	dirLayCnt := 4
1015
	var (
1016
		dirName      string
1017
		dirInoId     uint64 = 1
1018
		verArr       []uint64
1019
		renameDen    *Dentry
1020
		renameDstIno uint64
1021
		dirCnt       int
1022
		fileCnt      int
1023
	)
1024

1025
	for layIdx := 0; layIdx < dirLayCnt; layIdx++ {
1026
		t.Logf("build tree:layer %v,last dir name %v inodeid %v", layIdx, dirName, dirInoId)
1027
		dirIno := testCreateInode(t, DirModeType)
1028
		assert.True(t, dirIno != nil)
1029
		dirName = fmt.Sprintf("dir_layer_%v_1", layIdx+1)
1030
		dirDen := testCreateDentry(t, dirInoId, dirIno.Inode, dirName, DirModeType)
1031
		assert.True(t, dirDen != nil)
1032
		if dirDen == nil {
1033
			panic(nil)
1034
		}
1035
		dirIno1 := testCreateInode(t, DirModeType)
1036
		assert.True(t, dirIno1 != nil)
1037
		dirName1 := fmt.Sprintf("dir_layer_%v_2", layIdx+1)
1038
		dirDen1 := testCreateDentry(t, dirInoId, dirIno1.Inode, dirName1, DirModeType)
1039
		assert.True(t, dirDen1 != nil)
1040

1041
		if layIdx == 2 {
1042
			renameDen = dirDen.Copy().(*Dentry)
1043
		}
1044
		if layIdx == 1 {
1045
			renameDstIno = dirIno1.Inode
1046
		}
1047
		for fileIdx := 0; fileIdx < (layIdx+1)*2; fileIdx++ {
1048
			fileIno := testCreateInode(t, FileModeType)
1049
			assert.True(t, dirIno != nil)
1050

1051
			fileName := fmt.Sprintf("layer_%v_file_%v", layIdx+1, fileIdx+1)
1052
			dirDen = testCreateDentry(t, dirIno.Inode, fileIno.Inode, fileName, FileModeType)
1053
			assert.True(t, dirDen != nil)
1054
		}
1055
		dirInoId = dirIno.Inode
1056
		ver := testGetlastVer()
1057
		verArr = append(verArr, ver)
1058

1059
		dCnt, fCnt := testPrintDirTree(t, 1, "root", ver)
1060
		if layIdx+1 < dirLayCnt {
1061
			log.LogDebugf("testCreateVer")
1062
			testCreateVer()
1063
		}
1064

1065
		log.LogDebugf("PrintALl verseq [%v] get dirCnt %v, fCnt %v mp verlist size %v", ver, dCnt, fCnt, len(mp.multiVersionList.VerList))
1066
	}
1067

1068
	t.Logf("---------------------------------------------------------------------")
1069
	t.Logf("--------testPrintDirTree by ver -------------------------------------")
1070
	t.Logf("---------------------------------------------------------------------")
1071
	for idx, ver := range verArr {
1072
		dCnt, fCnt := testPrintDirTree(t, 1, "root", ver)
1073
		t.Logf("---------------------------------------------------------------------")
1074
		t.Logf("PrintALl verseq [%v] get dirCnt %v, fCnt %v", ver, dCnt, fCnt)
1075
		assert.True(t, dCnt == dirCnt+2)
1076
		assert.True(t, fCnt == fileCnt+(idx+1)*2)
1077
		dirCnt = dCnt
1078
		fileCnt = fCnt
1079
	}
1080
	t.Logf("------------rename dir ----------------------")
1081
	if renameDen != nil {
1082
		t.Logf("try to move dir %v", renameDen)
1083
		assert.True(t, nil != mp.fsmDeleteDentry(renameDen, false))
1084
		renameDen.Name = fmt.Sprintf("rename_from_%v", renameDen.Name)
1085
		renameDen.ParentId = renameDstIno
1086

1087
		t.Logf("try to move to dir %v", renameDen)
1088
		assert.True(t, mp.fsmCreateDentry(renameDen, false) == proto.OpOk)
1089
		testPrintDirTree(t, 1, "root", 0)
1090
	}
1091
	delSnapshotList := func() {
1092
		t.Logf("---------------------------------------------------------------------")
1093
		t.Logf("--------testCleanSnapshot by ver-------------------------------------")
1094
		t.Logf("---------------------------------------------------------------------")
1095
		for idx, ver := range verArr {
1096
			t.Logf("---------------------------------------------------------------------")
1097
			t.Logf("index %v ver [%v] try to deletion", idx, ver)
1098
			log.LogDebugf("index %v ver [%v] try to deletion", idx, ver)
1099
			t.Logf("---------------------------------------------------------------------")
1100
			testCleanSnapshot(t, ver)
1101
			t.Logf("---------------------------------------------------------------------")
1102
			t.Logf("index %v ver [%v] after deletion mp inode freeList len %v", idx, ver, mp.freeList.Len())
1103
			log.LogDebugf("index %v ver [%v] after deletion mp inode freeList len %v", idx, ver, mp.freeList.Len())
1104
			t.Logf("---------------------------------------------------------------------")
1105
			if idx == len(verArr)-2 {
1106
				break
1107
			}
1108
		}
1109
	}
1110
	delCurrent := func() {
1111
		t.Logf("---------------------------------------------------------------------")
1112
		t.Logf("--------testDeleteAll current -------------------------------------")
1113
		t.Logf("---------------------------------------------------------------------")
1114
		log.LogDebugf("try to deletion current")
1115
		testDeleteDirTree(t, 1, 0)
1116
		log.LogDebugf("try to deletion current finish")
1117
	}
1118

1119
	if topFirst {
1120
		delCurrent()
1121
		delSnapshotList()
1122
	} else {
1123
		delSnapshotList()
1124
		delCurrent()
1125
	}
1126

1127
	t.Logf("---------------------------------------------------------------------")
1128
	t.Logf("after deletion current layerr mp inode freeList len %v fileCnt %v dircnt %v", mp.freeList.Len(), fileCnt, dirCnt)
1129
	assert.True(t, mp.freeList.Len() == fileCnt)
1130
	// base on 3.2.0 the dir will push to freelist, not count in in later release version
1131
	// assert.True(t, mp.freeList.Len() == fileCnt+dirCnt)
1132
	assert.True(t, 0 == testPrintAllDentry(t))
1133
	t.Logf("---------------------------------------------------------------------")
1134

1135
	t.Logf("---------------------------------------------------------------------")
1136
	t.Logf("--------testPrintAllInodeInfo should have no inode -------------------------------------")
1137
	t.Logf("---------------------------------------------------------------------")
1138
	testPrintAllInodeInfo(t)
1139
	t.Logf("---------------------------------------------")
1140
	// assert.True(t, false)
1141
}
1142

1143
// create
1144
func TestSnapshotDeletion(t *testing.T) {
1145
	testSnapshotDeletion(t, true)
1146
	testSnapshotDeletion(t, false)
1147
}
1148

1149
func TestDentryVerMarshal(t *testing.T) {
1150
	initMp(t)
1151
	mp.verSeq = 10
1152
	den1 := &Dentry{
1153
		ParentId:  1,
1154
		Name:      "txt",
1155
		Inode:     10,
1156
		multiSnap: NewDentrySnap(mp.GetVerSeq()),
1157
	}
1158
	val, err := den1.Marshal()
1159
	if err != nil {
1160
		return
1161
	}
1162

1163
	den2 := &Dentry{}
1164
	den2.Unmarshal(val)
1165
	t.Logf("seq, %v %v,parent %v", den1.getVerSeq(), den2.getVerSeq(), den2.ParentId)
1166
	assert.True(t, den1.getVerSeq() == den2.getVerSeq())
1167
	assert.True(t, reflect.DeepEqual(den1, den2))
1168
}
1169

1170
func TestInodeVerMarshal(t *testing.T) {
1171
	initMp(t)
1172
	var topSeq uint64 = 10
1173
	var sndSeq uint64 = 2
1174
	mp.verSeq = 100000
1175
	ino1 := NewInode(10, 5)
1176
	ino1.setVer(topSeq)
1177
	ino1_1 := NewInode(10, 5)
1178
	ino1_1.setVer(sndSeq)
1179

1180
	ino1.multiSnap.multiVersions = append(ino1.multiSnap.multiVersions, ino1_1)
1181
	v1, _ := ino1.Marshal()
1182

1183
	ino2 := NewInode(0, 0)
1184
	ino2.Unmarshal(v1)
1185

1186
	assert.True(t, ino2.getVer() == topSeq)
1187
	assert.True(t, ino2.getLayerLen() == ino1.getLayerLen())
1188
	assert.True(t, ino2.getLayerVer(0) == sndSeq)
1189
	assert.True(t, reflect.DeepEqual(ino1, ino2))
1190
}
1191

1192
func TestSplitKey(t *testing.T) {
1193
	dp := &DataPartition{
1194
		PartitionID: 10,
1195
		Hosts:       []string{"192.168.0.1", "192.168.0.2", "192.168.0.3"},
1196
	}
1197
	ext := &proto.ExtentKey{
1198
		ExtentId:     28,
1199
		ExtentOffset: 10,
1200
		Size:         util.PageSize,
1201
		SnapInfo: &proto.ExtSnapInfo{
1202
			IsSplit: true,
1203
		},
1204
	}
1205
	_, invalid := NewPacketToDeleteExtent(dp, ext)
1206
	assert.True(t, invalid == true)
1207

1208
	ext.ExtentOffset = 0
1209
	_, invalid = NewPacketToDeleteExtent(dp, ext)
1210
	assert.True(t, invalid == false)
1211

1212
	ext.ExtentOffset = 10
1213
	ext.Size = 2 * util.PageSize
1214
	_, invalid = NewPacketToDeleteExtent(dp, ext)
1215
	assert.True(t, invalid == false)
1216
}
1217

1218
func NewMetaPartitionForTest() *metaPartition {
1219
	mpC := &MetaPartitionConfig{
1220
		PartitionId: PartitionIdForTest,
1221
		VolName:     VolNameForTest,
1222
	}
1223
	partition := NewMetaPartition(mpC, nil).(*metaPartition)
1224
	partition.uniqChecker.keepTime = 1
1225
	partition.uniqChecker.keepOps = 0
1226
	partition.mqMgr = NewQuotaManager(VolNameForTest, 1)
1227

1228
	return partition
1229
}
1230

1231
func mockPartitionRaftForTest(ctrl *gomock.Controller) *metaPartition {
1232
	partition := NewMetaPartitionForTest()
1233
	raft := raftstoremock.NewMockPartition(ctrl)
1234
	idx := uint64(0)
1235
	raft.EXPECT().Submit(gomock.Any()).DoAndReturn(func(cmd []byte) (resp interface{}, err error) {
1236
		idx++
1237
		return partition.Apply(cmd, idx)
1238
	}).AnyTimes()
1239

1240
	raft.EXPECT().IsRaftLeader().DoAndReturn(func(cmd []byte) (resp interface{}, err error) {
1241
		return true, nil
1242
	}).AnyTimes()
1243

1244
	raft.EXPECT().LeaderTerm().Return(uint64(1), uint64(1)).AnyTimes()
1245
	partition.raftPartition = raft
1246
	return partition
1247
}
1248

1249
func TestCheckVerList(t *testing.T) {
1250
	newMpWithMock(t)
1251
	mp.multiVersionList.VerList = append(mp.multiVersionList.VerList,
1252
		[]*proto.VolVersionInfo{
1253
			{Ver: 20, Status: proto.VersionNormal},
1254
			{Ver: 30, Status: proto.VersionNormal},
1255
			{Ver: 40, Status: proto.VersionNormal},
1256
		}...)
1257

1258
	masterList := &proto.VolVersionInfoList{
1259
		VerList: []*proto.VolVersionInfo{
1260
			{Ver: 0, Status: proto.VersionNormal},
1261
			{Ver: 20, Status: proto.VersionNormal},
1262
			{Ver: 30, Status: proto.VersionNormal},
1263
			{Ver: 40, Status: proto.VersionNormal},
1264
			{Ver: 50, Status: proto.VersionNormal},
1265
		},
1266
	}
1267
	var verData []byte
1268
	mp.checkVerList(masterList, false)
1269
	verData = <-mp.verUpdateChan
1270
	mp.submit(opFSMVersionOp, verData)
1271
	assert.True(t, mp.verSeq == 50)
1272
	assert.True(t, mp.multiVersionList.VerList[len(mp.multiVersionList.VerList)-1].Ver == 50)
1273

1274
	masterList = &proto.VolVersionInfoList{
1275
		VerList: []*proto.VolVersionInfo{
1276
			{Ver: 20, Status: proto.VersionNormal},
1277
			{Ver: 40, Status: proto.VersionNormal},
1278
		},
1279
	}
1280

1281
	needUpdate, _ := mp.checkVerList(masterList, false)
1282
	assert.True(t, needUpdate == false)
1283

1284
	assert.True(t, mp.verSeq == 50)
1285
	assert.True(t, len(mp.multiVersionList.VerList) == 5)
1286
	mp.stop()
1287
}
1288

1289
func checkStoreMode(t *testing.T, ExtentType uint8) (err error) {
1290
	if proto.IsTinyExtentType(ExtentType) || proto.IsNormalExtentType(ExtentType) {
1291
		return
1292
	}
1293
	t.Logf("action[checkStoreMode] extent type %v", ExtentType)
1294
	return fmt.Errorf("error")
1295
}
1296

1297
func TestCheckMod(t *testing.T) {
1298
	var tp uint8 = 192
1299
	err := checkStoreMode(t, tp)
1300
	assert.True(t, err == nil)
1301
}
1302

1303
func managerVersionPrepare(req *proto.MultiVersionOpRequest) (err error) {
1304
	if err, _ = manager.prepareCreateVersion(req); err != nil {
1305
		return
1306
	}
1307
	return manager.commitCreateVersion(req.VolumeID, req.VerSeq, req.Op, true)
1308
}
1309

1310
func newMpWithMock(t *testing.T) {
1311
	mockCtrl := gomock.NewController(t)
1312
	defer mockCtrl.Finish()
1313
	mp = mockPartitionRaftForTest(mockCtrl)
1314

1315
	mp.verUpdateChan = make(chan []byte, 100)
1316
	mp.config = metaConf
1317
	mp.config.Cursor = 0
1318
	mp.config.End = 100000
1319
	mp.uidManager = NewUidMgr(metaConf.VolName, metaConf.PartitionId)
1320
	mp.mqMgr = NewQuotaManager(metaConf.VolName, metaConf.PartitionId)
1321
	mp.multiVersionList.VerList = append(mp.multiVersionList.VerList, &proto.VolVersionInfo{
1322
		Ver: 0,
1323
	})
1324
	mp.multiVersionList.TemporaryVerMap = make(map[uint64]*proto.VolVersionInfo)
1325
}
1326

1327
func TestOpCommitVersion(t *testing.T) {
1328
	mockCtrl := gomock.NewController(t)
1329
	defer mockCtrl.Finish()
1330
	for i := 1; i < 5; i++ {
1331
		mp = mockPartitionRaftForTest(mockCtrl)
1332
		mp.config.PartitionId = uint64(i)
1333
		mp.manager = manager
1334
		mp.manager.partitions[mp.config.PartitionId] = mp
1335
		mp.config.NodeId = 1
1336
	}
1337

1338
	err := managerVersionPrepare(&proto.MultiVersionOpRequest{VolumeID: VolNameForTest, Op: proto.CreateVersionPrepare, VerSeq: 10000})
1339
	assert.True(t, err == nil)
1340
	for _, m := range manager.partitions {
1341
		mList := m.GetVerList()
1342
		assert.True(t, len(mList) == 1)
1343
		assert.True(t, mList[0].Ver == 10000)
1344
		assert.True(t, mList[0].Status == proto.VersionPrepare)
1345
	}
1346
	err = manager.commitCreateVersion(VolNameForTest, 10000, proto.CreateVersionPrepare, true)
1347
	assert.True(t, err == nil)
1348
	for _, m := range manager.partitions {
1349
		mList := m.GetVerList()
1350
		assert.True(t, len(mList) == 1)
1351
		assert.True(t, mList[0].Ver == 10000)
1352
		assert.True(t, mList[0].Status == proto.VersionPrepare)
1353
	}
1354
	err = managerVersionPrepare(&proto.MultiVersionOpRequest{VolumeID: VolNameForTest, Op: proto.CreateVersionPrepare, VerSeq: 5000})
1355
	assert.True(t, err == nil)
1356
	for _, m := range manager.partitions {
1357
		mList := m.GetVerList()
1358
		assert.True(t, len(mList) == 1)
1359
		assert.True(t, mList[0].Ver == 10000)
1360
		assert.True(t, mList[0].Status == proto.VersionPrepare)
1361
	}
1362
	err = managerVersionPrepare(&proto.MultiVersionOpRequest{VolumeID: VolNameForTest, Op: proto.CreateVersionPrepare, VerSeq: 20000})
1363
	assert.True(t, err == nil)
1364
	for _, m := range manager.partitions {
1365
		mList := m.GetVerList()
1366
		assert.True(t, len(mList) == 2)
1367
		assert.True(t, mList[0].Ver == 10000)
1368
		assert.True(t, mList[0].Status == proto.VersionPrepare)
1369
		assert.True(t, mList[1].Ver == 20000)
1370
		assert.True(t, mList[1].Status == proto.VersionPrepare)
1371
	}
1372
	err = manager.commitCreateVersion(VolNameForTest, 20000, proto.CreateVersionCommit, true)
1373
	assert.True(t, err == nil)
1374
	for _, m := range manager.partitions {
1375
		mList := m.GetVerList()
1376
		assert.True(t, len(mList) == 2)
1377
		assert.True(t, mList[0].Ver == 10000)
1378
		assert.True(t, mList[0].Status == proto.VersionPrepare)
1379
		assert.True(t, mList[1].Ver == 20000)
1380
		assert.True(t, mList[1].Status == proto.VersionNormal)
1381
	}
1382
}
1383

1384
func TestExtendSerialization(t *testing.T) {
1385
	dataMap := map[string][]byte{
1386
		"key1": []byte("value1"),
1387
		"key2": []byte("value2"),
1388
	}
1389
	mv := &Extend{
1390
		inode:   123,
1391
		dataMap: dataMap,
1392
		verSeq:  456,
1393
	}
1394

1395
	checkFunc := func() {
1396
		bytes, err := mv.Bytes()
1397
		if err != nil {
1398
			t.Errorf("Failed to serialize Extend: %v", err)
1399
		}
1400

1401
		newExtend, err := NewExtendFromBytes(bytes)
1402
		if err != nil {
1403
			t.Errorf("Failed to deserialize Extend: %v", err)
1404
		}
1405

1406
		if !reflect.DeepEqual(mv, newExtend) {
1407
			t.Errorf("Deserialized Extend does not match the original object")
1408
		}
1409
	}
1410

1411
	checkFunc()
1412

1413
	mv.multiVers = []*Extend{
1414
		{
1415
			inode:   789,
1416
			dataMap: map[string][]byte{"key3": []byte("value3")},
1417
			verSeq:  999,
1418
		},
1419
		{
1420
			inode:   789,
1421
			dataMap: map[string][]byte{"key4": []byte("value4")},
1422
			verSeq:  1999,
1423
		},
1424
	}
1425
	checkFunc()
1426
}
1427

1428
func TestXAttrOperation(t *testing.T) {
1429
	newMpWithMock(t)
1430

1431
	mp.SetXAttr(&proto.SetXAttrRequest{Key: "test", Value: "value"}, &Packet{})
1432
	mp.SetXAttr(&proto.SetXAttrRequest{Key: "test1", Value: "value1"}, &Packet{})
1433

1434
	testCreateVer()
1435

1436
	// operation on top of snapshot version
1437
	err := mp.SetXAttr(&proto.SetXAttrRequest{Key: "test1", Value: "value2"}, &Packet{})
1438
	assert.True(t, err == nil)
1439
	packRsp := &Packet{}
1440
	mp.GetXAttr(&proto.GetXAttrRequest{Key: "test1", VerSeq: 0}, packRsp)
1441
	assert.True(t, packRsp.ResultCode == proto.OpOk)
1442
	resp := new(proto.GetXAttrResponse)
1443
	err = packRsp.UnmarshalData(resp)
1444
	assert.True(t, err == nil)
1445
	assert.True(t, resp.Value == "value2")
1446

1447
	// remove test1 but it should exist in snapshot
1448
	err = mp.RemoveXAttr(&proto.RemoveXAttrRequest{Key: "test1"}, &Packet{})
1449
	assert.True(t, err == nil)
1450

1451
	mp.GetXAttr(&proto.GetXAttrRequest{Key: "test1", VerSeq: 0}, packRsp)
1452
	assert.True(t, packRsp.ResultCode == proto.OpOk)
1453
	err = packRsp.UnmarshalData(resp)
1454
	assert.True(t, err == nil)
1455
	assert.True(t, resp.Value == "")
1456

1457
	// get snapshot xattr the 0 version
1458
	packRsp = &Packet{}
1459
	mp.GetXAttr(&proto.GetXAttrRequest{Key: "test1", VerSeq: math.MaxUint64}, packRsp)
1460
	assert.True(t, packRsp.ResultCode == proto.OpOk)
1461

1462
	resp = new(proto.GetXAttrResponse)
1463
	err = packRsp.UnmarshalData(resp)
1464
	assert.True(t, err == nil)
1465
	assert.True(t, resp.Value == "value1")
1466
}
1467

1468
func TestUpdateDenty(t *testing.T) {
1469
	newMpWithMock(t)
1470
	testCreateInode(nil, DirModeType)
1471
	err := mp.CreateDentry(&CreateDentryReq{Name: "testfile", ParentID: 1, Inode: 1000}, &Packet{}, localAddrForAudit)
1472
	assert.True(t, err == nil)
1473
	testCreateVer()
1474
	mp.UpdateDentry(&UpdateDentryReq{Name: "testfile", ParentID: 1, Inode: 2000}, &Packet{}, localAddrForAudit)
1475
	den := &Dentry{Name: "testfile", ParentId: 1}
1476
	den.setVerSeq(math.MaxUint64)
1477
	denRsp, status := mp.getDentry(den)
1478
	assert.True(t, status == proto.OpOk)
1479
	assert.True(t, denRsp.Inode == 1000)
1480
}
1481

1482
func TestCheckEkEqual(t *testing.T) {
1483
	ek1 := &proto.ExtentKey{FileOffset: 10, SnapInfo: &proto.ExtSnapInfo{VerSeq: 10, IsSplit: true}}
1484
	ek2 := &proto.ExtentKey{FileOffset: 10, SnapInfo: &proto.ExtSnapInfo{VerSeq: 10, IsSplit: true}}
1485
	assert.True(t, ek1.Equals(ek2))
1486
}
1487

1488
func TestDelPartitionVersion(t *testing.T) {
1489
	manager = &metadataManager{partitions: make(map[uint64]MetaPartition), volUpdating: new(sync.Map)}
1490
	newMpWithMock(t)
1491
	mp.config.PartitionId = metaConf.PartitionId
1492
	mp.manager = manager
1493
	mp.manager.partitions[mp.config.PartitionId] = mp
1494
	mp.config.NodeId = 1
1495

1496
	err := managerVersionPrepare(&proto.MultiVersionOpRequest{VolumeID: VolNameForTest, Op: proto.CreateVersionPrepare, VerSeq: 10})
1497
	assert.True(t, err == nil)
1498

1499
	ino := testCreateInode(t, FileModeType)
1500
	assert.True(t, ino.getVer() == 10)
1501
	mp.SetXAttr(&proto.SetXAttrRequest{Inode: ino.Inode, Key: "key1", Value: "0000"}, &Packet{})
1502
	mp.CreateDentry(&CreateDentryReq{Inode: ino.Inode, Name: "dentryName"}, &Packet{}, "/dentryName")
1503

1504
	err = managerVersionPrepare(&proto.MultiVersionOpRequest{VolumeID: VolNameForTest, Op: proto.CreateVersionPrepare, VerSeq: 25})
1505
	mp.SetXAttr(&proto.SetXAttrRequest{Inode: ino.Inode, Key: "key1", Value: "1111"}, &Packet{})
1506

1507
	assert.True(t, err == nil)
1508

1509
	extend := mp.extendTree.Get(NewExtend(ino.Inode)).(*Extend)
1510
	assert.True(t, len(extend.multiVers) == 1)
1511

1512
	masterList := &proto.VolVersionInfoList{
1513
		VerList: []*proto.VolVersionInfo{
1514
			{Ver: 20, Status: proto.VersionNormal},
1515
			{Ver: 30, Status: proto.VersionNormal},
1516
			{Ver: 40, Status: proto.VersionNormal},
1517
			{Ver: 50, Status: proto.VersionNormal},
1518
		},
1519
	}
1520
	mp.checkByMasterVerlist(mp.multiVersionList, masterList)
1521
	mp.checkVerList(masterList, true)
1522
	assert.True(t, len(mp.multiVersionList.TemporaryVerMap) == 2)
1523

1524
	mp.SetXAttr(&proto.SetXAttrRequest{Inode: ino.Inode, Key: "key1", Value: "2222"}, &Packet{})
1525

1526
	go mp.multiVersionTTLWork(time.Millisecond * 10)
1527

1528
	cnt := 30
1529
	for cnt > 0 {
1530
		if len(mp.multiVersionList.TemporaryVerMap) != 0 {
1531
			time.Sleep(time.Millisecond * 100)
1532
			cnt--
1533
			continue
1534
		}
1535
		break
1536
	}
1537
	inoNew := mp.getInode(&Inode{Inode: ino.Inode}, false).Msg
1538
	assert.True(t, inoNew.getVer() == 25)
1539
	extend = mp.extendTree.Get(NewExtend(ino.Inode)).(*Extend)
1540
	t.Logf("extent verseq [%v], multivers %v", extend.verSeq, extend.multiVers)
1541
	assert.True(t, extend.verSeq == 50)
1542
	assert.True(t, len(extend.multiVers) == 1)
1543
	assert.True(t, extend.multiVers[0].verSeq == 25)
1544

1545
	assert.True(t, string(extend.multiVers[0].dataMap["key1"]) == "1111")
1546

1547
	err = extend.checkSequence()
1548
	t.Logf("extent checkSequence err %v", err)
1549
	assert.True(t, err == nil)
1550
	assert.True(t, len(mp.multiVersionList.TemporaryVerMap) == 0)
1551
}
1552

1553
func TestMpMultiVerStore(t *testing.T) {
1554
	initMp(t)
1555
	filePath := "/tmp/"
1556
	crc, _ := mp.storeMultiVersion(filePath, &storeMsg{
1557
		multiVerList: []*proto.VolVersionInfo{{Ver: 20, Status: proto.VersionNormal}, {Ver: 30, Status: proto.VersionNormal}},
1558
	})
1559
	err := mp.loadMultiVer(filePath, crc)
1560
	assert.True(t, err == nil)
1561
}
1562

1563
func TestGetAllVerList(t *testing.T) {
1564
	initMp(t)
1565
	mp.multiVersionList = &proto.VolVersionInfoList{
1566
		VerList: []*proto.VolVersionInfo{
1567
			{Ver: 20, Status: proto.VersionNormal},
1568
			{Ver: 30, Status: proto.VersionNormal},
1569
			{Ver: 40, Status: proto.VersionNormal},
1570
			{Ver: 50, Status: proto.VersionNormal},
1571
		},
1572
	}
1573
	tmp := mp.multiVersionList.VerList
1574
	mp.multiVersionList.VerList = append(mp.multiVersionList.VerList[:1], mp.multiVersionList.VerList[2:]...)
1575
	tmp = append(tmp, &proto.VolVersionInfo{Ver: 30, Status: proto.VersionNormal})
1576

1577
	sort.SliceStable(tmp, func(i, j int) bool {
1578
		if tmp[i].Ver < tmp[j].Ver {
1579
			return true
1580
		}
1581
		return false
1582
	})
1583

1584
	t.Logf("tmp[%v]", tmp)
1585
	t.Logf("mp.multiVersionList %v", mp.multiVersionList)
1586

1587
	mp.multiVersionList.TemporaryVerMap = make(map[uint64]*proto.VolVersionInfo)
1588
	mp.multiVersionList.TemporaryVerMap[25] = &proto.VolVersionInfo{Ver: 25, Status: proto.VersionNormal}
1589
	mp.multiVersionList.TemporaryVerMap[45] = &proto.VolVersionInfo{Ver: 45, Status: proto.VersionNormal}
1590
	newList := mp.GetAllVerList()
1591
	oldList := mp.multiVersionList.VerList
1592
	t.Logf("newList %v oldList %v", newList, oldList)
1593
	assert.True(t, true)
1594
}
1595

1596
func TestVerlistSnapshot(t *testing.T) {
1597
	verList := []*proto.VolVersionInfo{
1598
		{Ver: 20, Status: proto.VersionNormal},
1599
	}
1600
	var verListBuf1 []byte
1601
	var err error
1602
	if verListBuf1, err = json.Marshal(verList); err != nil {
1603
		return
1604
	}
1605
	t.Logf("mp.TestVerlistSnapshot  %v", verListBuf1)
1606
	var verList12 []*proto.VolVersionInfo
1607
	if err = json.Unmarshal(verListBuf1, &verList12); err != nil {
1608
		t.Logf("mp.TestVerlistSnapshot  err %v", err)
1609
	}
1610
	t.Logf("mp.TestVerlistSnapshot  %v", verList12)
1611
	assert.True(t, true)
1612
}
1613

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.