diff --git a/communication/SyncLogicHandler.go b/communication/SyncLogicHandler.go index 1c2f85a..188720f 100644 --- a/communication/SyncLogicHandler.go +++ b/communication/SyncLogicHandler.go @@ -50,7 +50,7 @@ type SyncLogicHandler struct { // confParam MLSR配置参数 confParam *common.MlsrConfigParameters // nlsrComponent NLSR字符串 - nlsrComponent string + mlsrComponent string // lsaComponent LSA字符串 lsaComponent string /////////////// 公有属性 ///////////// @@ -80,17 +80,17 @@ func (s *SyncLogicHandler) ProcessUpdate(updateName *component.Identifier, highS common2.LogInfo("Update Name: ", updateName.ToUri(), " Seq no: ", highSeq) // nlsrPosition 从同步数据的标识中获取子字符串'nlsr'的位置 - nlsrPosition := utils.GetNameComponentPosition(updateName, s.nlsrComponent) + mlsrPosition := utils.GetNameComponentPosition(updateName, s.mlsrComponent) // lsaPosition 从同步数据的标识中获取子字符串'lsa'的位置 lsaPosition := utils.GetNameComponentPosition(updateName, s.lsaComponent) - if nlsrPosition < 0 || lsaPosition < 0 { + if mlsrPosition < 0 || lsaPosition < 0 { common2.LogWarn("收到了不合法的同步更新数据") return } // networkName 用于表示源MLSR节点网络标识 - networkName, err := updateName.GetSubIdentifier(1, nlsrPosition-1) + networkName, err := updateName.GetSubIdentifier(1, mlsrPosition-1) if err != nil { common2.LogError("解析源MLSR节点网络标识出错", err.Error()) return @@ -128,6 +128,7 @@ func (s *SyncLogicHandler) ProcessUpdate(updateName *component.Identifier, highS originRouterName.Append(comp) } + s.ProcessUpdateFromSync(originRouterName, updateName, highSeq, incomingFaceId) } // ProcessUpdateFromSync 处理更新的回调函数 @@ -213,36 +214,37 @@ func NewSyncLogicHandler(face *logicface.DummyClientLogicFace, isLsaNew IsLsaNew syncLogicHandler.confParam = conf // 标识组件构造 - syncLogicHandler.nlsrComponent = "nlsr" - syncLogicHandler.lsaComponent = "lsa" + syncLogicHandler.mlsrComponent = "mlsr" + syncLogicHandler.lsaComponent = "LSA" // NLSR的源码中使用了字符串类型的标识组件, 而不是非负数类型 nameComponent := component.CreateIdentifierComponentByString(strconv.Itoa(int(lsa.LsaNAMEType))) adjComponent := component.CreateIdentifierComponentByString(strconv.Itoa(int(lsa.LsaADJACENCYType))) coorComponent := component.CreateIdentifierComponentByString(strconv.Itoa(int(lsa.LsaCOORDINATEType))) - // 复制标识SyncUserPrefix - syncPrefix := conf.GetSyncPrefix() - if syncPrefix == nil { + // Bug: 复制标识SyncPrefix + // Fix: 复制标识SyncUserPrefix + syncUserPrefix := conf.GetSyncUserPrefix() + if syncUserPrefix == nil { return nil, errors.New("无效同步标识") } - syncPrefixBlock, err := syncPrefix.SelfWireEncode(syncPrefix) + syncUserPrefixBlock, err := syncUserPrefix.SelfWireEncode(syncUserPrefix) if err != nil { return nil, err } // NameLsaUserPrefix 构建 - syncLogicHandler.NameLsaUserPrefix, err = component.NewIdentifierByBlock(syncPrefixBlock) + syncLogicHandler.NameLsaUserPrefix, err = component.NewIdentifierByBlock(syncUserPrefixBlock) if err != nil { return nil, err } syncLogicHandler.NameLsaUserPrefix.Append(nameComponent) // AdjLsaUserPrefix 构建 - syncLogicHandler.AdjLsaUserPrefix, err = component.NewIdentifierByBlock(syncPrefixBlock) + syncLogicHandler.AdjLsaUserPrefix, err = component.NewIdentifierByBlock(syncUserPrefixBlock) if err != nil { return nil, err } syncLogicHandler.AdjLsaUserPrefix.Append(adjComponent) // CoorLsaUserPrefix 构建 - syncLogicHandler.CoorLsaUserPrefix, err = component.NewIdentifierByBlock(syncPrefixBlock) + syncLogicHandler.CoorLsaUserPrefix, err = component.NewIdentifierByBlock(syncUserPrefixBlock) if err != nil { return nil, err } diff --git a/communication/SyncLogicHandler_test.go b/communication/SyncLogicHandler_test.go new file mode 100644 index 0000000..6e120b5 --- /dev/null +++ b/communication/SyncLogicHandler_test.go @@ -0,0 +1,337 @@ +// Package communication +// @Author: zhengqi Wu +// @Description: +// @Version: 0.1.0 +// @Date: 2022/8/10 16:07 +// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 +// + +package communication + +import ( + "MINSync" + "fmt" + "github.com/stretchr/testify/assert" + common2 "minlib/common" + "minlib/component" + "minlib/logicface" + "minlib/utils" + "mlsr/common" + "mlsr/lsa" + "strconv" + "testing" + "time" +) + +// SyncLogicFixture SyncLogic测试中固定不变的部分 +type SyncLogicFixture struct { + // 变量 + face *logicface.DummyClientLogicFace + conf *common.MlsrConfigParameters + testIsLsaNew IsLsaNew + // 同步逻辑实例 + sync *SyncLogicHandler + + // 常量 + updateNamePrefix string + lsaTypes [3]lsa.LsaType +} + +// receiveUpdate 模拟接收到更新后的处理流程 +// +func (this *SyncLogicFixture) receiveUpdate(prefix string, seqNo uint64) { + time.Sleep(10 * time.Millisecond) + this.face.SentInterests.Clear() + + // 模拟更新数据 + updates := make([]*MINSync.MissingDataInfo, 0) + prefixInIdentifier, _ := component.NewIdentifierByString(prefix) + updates = append(updates, MINSync.NewMissingDataInfo(prefixInIdentifier, 0, seqNo, 0)) + // 通知SyncLogic处理更新数据 + this.sync.SyncLogic.OnMINSyncUpdate(updates) +} + +// NewSyncLogicFixture SyncLogicFixture的工厂方法 +func NewSyncLogicFixture() *SyncLogicFixture { + syncLogicFixture := new(SyncLogicFixture) + syncLogicFixture.face = logicface.NewDummyClientLogicFaceByOptions("face0", "", logicface.NewDummyClientOptionsByParams(true, true)) + syncLogicFixture.testIsLsaNew = func(identifier *component.Identifier, lsaType lsa.LsaType, seq uint64, incomingLogicFaceId uint64) bool { + return true + } + + // 初始化MLSR配置 + // TODO: 这里写死是为了测试,真实使用不能这么写 + mlsrConfig, _ := common.ParseConfig("E:/mir-dir/mlsr/mlsrConf.ini") + syncLogicFixture.conf = new(common.MlsrConfigParameters) + syncLogicFixture.conf.Init(mlsrConfig) + + syncLogicFixture.sync, _ = NewSyncLogicHandler(syncLogicFixture.face, syncLogicFixture.testIsLsaNew, syncLogicFixture.conf) + syncLogicFixture.updateNamePrefix = + syncLogicFixture.conf.GetLsaPrefix().ToUri() + + syncLogicFixture.conf.GetSiteName().ToUri() + + "/C1.Router/other-router/" + + // 初始化lsaTypes,按顺序填充 + syncLogicFixture.lsaTypes = *(new([3]lsa.LsaType)) + syncLogicFixture.lsaTypes[0] = lsa.LsaNAMEType + syncLogicFixture.lsaTypes[1] = lsa.LsaADJACENCYType + syncLogicFixture.lsaTypes[2] = lsa.LsaCOORDINATEType + + return syncLogicFixture +} + +// TestUpdateForOtherLS +// +// 该测试用例主要用于测试当SyncLogicHandler收到更新的NameLSA或ADJLSA时, +// 是否会将该LSA及其细节通过信号通知MLSR +// +func TestUpdateForOtherLS(t *testing.T) { + fixture := NewSyncLogicFixture() + + // nCallBacks 用于统计回调函数的调用次数 + nCallBacks := 0 + // syncSeqNo 手工指定的同步数据的序列号 + var syncSeqNo uint64 = 1 + + lsaTypes := []lsa.LsaType{lsa.LsaNAMEType, lsa.LsaADJACENCYType} + var conn *utils.Connection + for _, lsaType := range lsaTypes { + // Fix: 模拟ScopedConnection 手动释放信号 + if conn != nil { + conn.Disconnect() + } + updateName := fmt.Sprintf("%s%d", fixture.updateNamePrefix, lsaType) + // Bug: 在NLSR中使用的是ScopedConnection,意味着每当一次循环结束后,该连接就自动解除 + conn = fixture.sync.OnNewLsa.Connect(func(i ...interface{}) { + routerName := i[0].(*component.Identifier) + sequenceNumber := i[1].(uint64) + // originRouter := i[2].(*component.Identifier) + // incomingFaceId := i[3].(uint64) + + // 检查更新的同步数据前缀是否相等 + assert.Equal(t, updateName, routerName.ToUri()) + // 检查更新的同步数据序列号是否相等 + assert.Equal(t, sequenceNumber, syncSeqNo) + nCallBacks += 1 + }) + fixture.receiveUpdate(updateName, syncSeqNo) + } + + assert.Equal(t, nCallBacks, 2) +} + +// TestUpdateForOtherHR +// +// 该测试用例主要用于测试当SyncLogicHandler收到更新的NameLSA或CoordinateLSA时, +// 是否会将该LSA及其细节通过信号通知MLSR +// +func TestUpdateForOtherHR(t *testing.T) { + fixture := NewSyncLogicFixture() + + // nCallBacks 用于统计回调函数的调用次数 + nCallBacks := 0 + // syncSeqNo 手工指定的同步数据的序列号 + var syncSeqNo uint64 = 1 + + lsaTypes := []lsa.LsaType{lsa.LsaNAMEType, lsa.LsaCOORDINATEType} + var conn *utils.Connection + for _, lsaType := range lsaTypes { + // Fix: 模拟ScopedConnection 手动释放信号 + if conn != nil { + conn.Disconnect() + } + updateName := fmt.Sprintf("%s%d", fixture.updateNamePrefix, lsaType) + // Bug: 在NLSR中使用的是ScopedConnection,意味着每当一次循环结束后,该连接就自动解除 + conn = fixture.sync.OnNewLsa.Connect(func(i ...interface{}) { + routerName := i[0].(*component.Identifier) + sequenceNumber := i[1].(uint64) + // originRouter := i[2].(*component.Identifier) + // incomingFaceId := i[3].(uint64) + + // 检查更新的同步数据前缀是否相等 + assert.Equal(t, updateName, routerName.ToUri()) + // 检查更新的同步数据序列号是否相等 + assert.Equal(t, sequenceNumber, syncSeqNo) + nCallBacks += 1 + }) + fixture.receiveUpdate(updateName, syncSeqNo) + } + + assert.Equal(t, nCallBacks, 2) +} + +// TestUpdateForOtherHRDry +// +// 该测试用例主要用于测试当SyncLogicHandler收到更新的任意类型的LSA时, +// 是否会将该LSA及其细节通过信号通知MLSR +// +func TestUpdateForOtherHRDry(t *testing.T) { + fixture := NewSyncLogicFixture() + + // nCallBacks 用于统计回调函数的调用次数 + nCallBacks := 0 + // syncSeqNo 手工指定的同步数据的序列号 + var syncSeqNo uint64 = 1 + + var conn *utils.Connection + for _, lsaType := range fixture.lsaTypes { + // Fix: 模拟ScopedConnection 手动释放信号 + if conn != nil { + conn.Disconnect() + } + updateName := fmt.Sprintf("%s%d", fixture.updateNamePrefix, lsaType) + // Bug: 在NLSR中使用的是ScopedConnection,意味着每当一次循环结束后,该连接就自动解除 + conn = fixture.sync.OnNewLsa.Connect(func(i ...interface{}) { + routerName := i[0].(*component.Identifier) + sequenceNumber := i[1].(uint64) + // originRouter := i[2].(*component.Identifier) + // incomingFaceId := i[3].(uint64) + + // 检查更新的同步数据前缀是否相等 + assert.Equal(t, updateName, routerName.ToUri()) + // 检查更新的同步数据序列号是否相等 + assert.Equal(t, sequenceNumber, syncSeqNo) + nCallBacks += 1 + }) + fixture.receiveUpdate(updateName, syncSeqNo) + } + + assert.Equal(t, nCallBacks, 3) +} + +// TestNoUpdateForSelf +// +// 该测试用例主要用于测试当SyncLogicHandler收到自身发布的任意更新数据时, +// 是否不会触发信号调用回调函数 +// +func TestNoUpdateForSelf(t *testing.T) { + fixture := NewSyncLogicFixture() + var sequenceNumber uint64 = 1 + + var conn *utils.Connection + for _, lsaType := range fixture.lsaTypes { + // Fix: 模拟ScopedConnection 手动释放信号 + if conn != nil { + conn.Disconnect() + } + // 为拷贝标识准备TLV Block + lsaPrefixBlockForCopy, _ := fixture.conf.GetLsaPrefix().SelfWireEncode(fixture.conf.GetLsaPrefix()) + siteNameBlockForCopy, _ := fixture.conf.GetSiteName().SelfWireEncode(fixture.conf.GetSiteName()) + routerNameBlockForCopy, _ := fixture.conf.GetRouterName().SelfWireEncode(fixture.conf.GetRouterName()) + + updateName, _ := component.NewIdentifierByBlock(lsaPrefixBlockForCopy) + // 拷贝siteName标识,并将副本的标识组件加入到updateName中 + siteNameCopy, _ := component.NewIdentifierByBlock(siteNameBlockForCopy) + for _, comp := range siteNameCopy.GetComponents() { + updateName.Append(comp) + } + // 拷贝routeName标识,并将副本的标识组件加入到updateName中 + routerNameCopy, _ := component.NewIdentifierByBlock(routerNameBlockForCopy) + for _, comp := range routerNameCopy.GetComponents() { + updateName.Append(comp) + } + // 添加LSAType字符串标识组件 + updateName.AppendString(strconv.Itoa(int(lsaType))) + + conn = fixture.sync.OnNewLsa.Connect(func(i ...interface{}) { + // 自身发布的更新不应该触发信号,因此这里Fatal掉 + common2.LogFatal("Updates for self should not be emitted!") + }) + + fixture.receiveUpdate(updateName.ToUri(), sequenceNumber) + } + + // 正常运行结束即算单元测试通过 +} + +// TestMalformedUpdate +// +// 该测试用例主要用于测试当SyncHandler收到不符合格式的异常更新数据时, +// 是否不会去触发信号通知MLSR +// +func TestMalformedUpdate(t *testing.T) { + fixture := NewSyncLogicFixture() + var sequenceNumber uint64 = 1 + + var conn *utils.Connection + for _, lsaType := range fixture.lsaTypes { + // Fix: 模拟ScopedConnection 手动释放信号 + if conn != nil { + conn.Disconnect() + } + // 为拷贝标识准备TLV Block + siteNameBlockForCopy, _ := fixture.conf.GetSiteName().SelfWireEncode(fixture.conf.GetSiteName()) + routerNameBlockForCopy, _ := fixture.conf.GetRouterName().SelfWireEncode(fixture.conf.GetRouterName()) + + updateName, _ := component.NewIdentifierByBlock(siteNameBlockForCopy) + // 拷贝routeName标识,并将副本的标识组件加入到updateName中 + routerNameCopy, _ := component.NewIdentifierByBlock(routerNameBlockForCopy) + for _, comp := range routerNameCopy.GetComponents() { + updateName.Append(comp) + } + // 添加LSAType字符串标识组件 + updateName.AppendString(strconv.Itoa(int(lsaType))) + + conn = fixture.sync.OnNewLsa.Connect(func(i ...interface{}) { + // 自身发布的更新不应该触发信号,因此这里Fatal掉 + common2.LogFatal("Updates for self should not be emitted!") + }) + + fixture.receiveUpdate(updateName.ToUri(), sequenceNumber) + } + + // 正常运行结束即算单元测试通过 +} + +// TestLsaNotNew +// +// 该测试用例主要用于测试当SyncHandler收到老版本的同步数据时, +// 是否不会去触发信号通知MLSR +// +func TestLsaNotNew(t *testing.T) { + fixture := NewSyncLogicFixture() + + // IsNewLSA 总返回false + testLsaAlwaysFalse := func(routerName *component.Identifier, + lsaType lsa.LsaType, + sequenceNumber uint64, + incomingFaceId uint64) bool { + return false + } + + var sequenceNumber uint64 = 1 + + // 新建一个使用testLsaAlwaysFalse作为IsNewLSA的SyncLogicHandler + sync, _ := NewSyncLogicHandler(fixture.face, testLsaAlwaysFalse, fixture.conf) + sync.OnNewLsa.Connect(func(i ...interface{}) { + // 由于没有收到新的LSA,因此该信号不会被触发 + common2.LogFatal("An update for an LSA with non-new sequence number should not emit!") + }) + + updateName := fixture.updateNamePrefix + strconv.Itoa(int(lsa.LsaNAMEType)) + + fixture.receiveUpdate(updateName, sequenceNumber) + + // 正常运行结束即算单元测试通过 +} + +// TestUpdatePrefix +// +// 本测试用例主要用于测试SyncLogicHandler是否将LsaPrefix SiteName RouterName成功组合在一起 +// +func TestUpdatePrefix(t *testing.T) { + fixture := NewSyncLogicFixture() + + expectedPrefix := fixture.conf.GetLsaPrefix() + for _, comp := range fixture.conf.GetSiteName().GetComponents() { + expectedPrefix.Append(comp) + } + + for _, comp := range fixture.conf.GetRouterName().GetComponents() { + expectedPrefix.Append(comp) + } + + assert.Equal(t, fixture.sync.NameLsaUserPrefix.ToUri(), expectedPrefix.ToUri()+"/"+strconv.Itoa(int(lsa.LsaNAMEType))) + assert.Equal(t, fixture.sync.AdjLsaUserPrefix.ToUri(), expectedPrefix.ToUri()+"/"+strconv.Itoa(int(lsa.LsaADJACENCYType))) + assert.Equal(t, fixture.sync.CoorLsaUserPrefix.ToUri(), expectedPrefix.ToUri()+"/"+strconv.Itoa(int(lsa.LsaCOORDINATEType))) +} diff --git a/communication/SyncProtocolAdapter_test.go b/communication/SyncProtocolAdapter_test.go new file mode 100644 index 0000000..fd87b24 --- /dev/null +++ b/communication/SyncProtocolAdapter_test.go @@ -0,0 +1,138 @@ +// Package communication +// @Author: zhengqi Wu +// @Description: +// @Version: 0.1.0 +// @Date: 2022/8/10 16:07 +// @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 +// + +package communication + +import ( + "fmt" + "github.com/stretchr/testify/assert" + "minlib/common" + "minlib/component" + "minlib/logicface" + "testing" + "time" +) + +// SyncProtocolAdapterFixture SyncProtocolAdapter单元测试中不变的部分 +type SyncProtocolAdapterFixture struct { + // syncPrefix 同步公共前缀 + syncPrefix *component.Identifier + // nameLsaUserPrefix + nameLsaUserPrefix *component.Identifier + // userPrefixes + userPrefixes [2]*component.Identifier + // syncInterestLifetime 同步兴趣包的生命周期 + syncInterestLifetime time.Duration + faces [2]*logicface.DummyClientLogicFace + nodes [2]*SyncProtocolAdapter + // prefixToSeq 前缀与序列号的映射表 + // NLSR中使用Identifier的地址作为map的key, + // 然而在本测试中无法保证两个内容一致的标识它们的指针地址也相同,所以使用标识的字符串作为map的key + prefixToSeq [2]map[string]uint64 +} + +// addNodes 准备路由同步节点 +// +func (f *SyncProtocolAdapterFixture) addNodes() { + nameLsaUserPrefixBlockForCopy, _ := f.nameLsaUserPrefix.SelfWireEncode(f.nameLsaUserPrefix) + for i := 0; i < 2; i++ { + // fix: 为循环的每一次闭包创建一个局部变量用来逃逸 + index := i + f.faces[i] = logicface.NewDummyClientLogicFaceByOptions(fmt.Sprintf("face%d", i), "", logicface.NewDummyClientOptionsByParams(true, true)) + f.userPrefixes[i], _ = component.NewIdentifierByBlock(nameLsaUserPrefixBlockForCopy) + f.userPrefixes[i].Append(component.CreateIdentifierComponentByNonNegativeInteger(uint64(i))) + f.nodes[i], _ = NewSyncProtocolAdapter(f.faces[i], f.syncPrefix, + f.userPrefixes[i], + f.syncInterestLifetime, + func(updateName *component.Identifier, seqNo uint64, incomingFaceId uint64) { + // bug: 闭包 变量i逃逸 导致数组访问越界 + // f.prefixToSeq[i][updateName.ToUri()] = seqNo + // common.LogInfo("逃逸的变量i赋值给本地局部变量index: ", index) + f.prefixToSeq[index][updateName.ToUri()] = seqNo + }) + } + f.faces[0].LinkTo(f.faces[1]) + time.Sleep(100 * time.Millisecond) +} + +// NewSyncProtocolAdapterFixture SyncProtocolAdapterFixture的工厂方法 +// +func NewSyncProtocolAdapterFixture() *SyncProtocolAdapterFixture { + // 基本数据类型 + fixture := new(SyncProtocolAdapterFixture) + fixture.syncPrefix, _ = component.NewIdentifierByString("/localhop/min/mlsr/sync") + fixture.nameLsaUserPrefix, _ = component.NewIdentifierByString("/localhop/min/mlsr/LSA/NAME") + // fixture.syncInterestLifetime = 60 * time.Second + // 由于MINSync实现的原因,为了实现正确的数据同步,将请求兴趣包的生命周期设为0.5s + fixture.syncInterestLifetime = 500 * time.Millisecond + fixture.syncPrefix.AppendVersionNumber(4) + + // 引用数据类型 + fixture.userPrefixes = *new([2]*component.Identifier) + fixture.nodes = *new([2]*SyncProtocolAdapter) + fixture.faces = *new([2]*logicface.DummyClientLogicFace) + fixture.prefixToSeq = *new([2]map[string]uint64) + fixture.prefixToSeq[0] = make(map[string]uint64) + fixture.prefixToSeq[1] = make(map[string]uint64) + + return fixture +} + +// TestBasicSyncProtocolAdapter SyncProtocolAdapter 基本用法 测试用例 +func TestBasicSyncProtocolAdapter(t *testing.T) { + // 设置日志输出参数 + common.InitLogger(&common.LoggerParameters{ + // ReportCaller 输出日志所处文件位置 + ReportCaller: true, + LogLevel: "", + LogFormat: "", + LogFilePath: "", + }) + + // 准备路由同步节点 + fixture := NewSyncProtocolAdapterFixture() + fixture.addNodes() + + // 节点 0 发布更新 + fixture.nodes[0].PublishUpdate(fixture.userPrefixes[0], 10) + time.Sleep(1000 * time.Millisecond) + + // 检查节点 1 的 prefixToSeq + seq, exist := fixture.prefixToSeq[1][fixture.userPrefixes[0].ToUri()] + assert.Equal(t, exist, true) + assert.Equal(t, seq, uint64(10)) + + // 节点 1 发布更新 + fixture.nodes[1].PublishUpdate(fixture.userPrefixes[1], 100) + time.Sleep(1000 * time.Millisecond) + + // 检查节点 0 的 prefixToSeq + seq, exist = fixture.prefixToSeq[0][fixture.userPrefixes[1].ToUri()] + assert.Equal(t, exist, true) + assert.Equal(t, seq, uint64(100)) + + // 为 节点0 新增数据前缀 + adjLsaUserPrefix, _ := component.NewIdentifierByString("/localhop/min/mlsr/LSA/ADJACENCY") + fixture.nodes[0].AddUserNode(adjLsaUserPrefix) + time.Sleep(10 * time.Millisecond) + // 为新增的数据前缀发布更新 + fixture.nodes[0].PublishUpdate(adjLsaUserPrefix, 10) + // 等待1到2个时间窗口,节点数据完成同步 + time.Sleep(1000 * time.Millisecond) + + // 检查节点1的prefixToSeq + seq, exist = fixture.prefixToSeq[1][adjLsaUserPrefix.ToUri()] + assert.Equal(t, exist, true) + assert.Equal(t, seq, uint64(10)) +} + +func TestBasicSyncProtocolAdapter_100times(t *testing.T) { + for i := 0; i < 100; i++ { + TestBasicSyncProtocolAdapter(t) + } +} diff --git a/go.mod b/go.mod index 680cd30..7679704 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module mlsr go 1.17 require ( + MINSync v0.0.0 //github.com/rakanalh/scheduler v0.1 github.com/go-co-op/gocron v1.13.0 github.com/liyue201/gostl v1.0.1 @@ -10,7 +11,6 @@ require ( github.com/tidwall/buntdb v1.2.9 gopkg.in/ini.v1 v1.62.0 minlib v0.0.0 - MINSync v0.0.0 ) require ( @@ -39,6 +39,7 @@ require ( github.com/tidwall/rtred v0.1.2 // indirect github.com/tidwall/tinyqueue v0.1.1 // indirect github.com/tylertreat/BoomFilters v0.0.0-20210315201527-1a82519a3e43 // indirect + github.com/vishalkuo/bimap v0.0.0-20180703190407-09cff2814645 // indirect github.com/zeebo/xxh3 v1.0.1 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect @@ -51,4 +52,5 @@ require ( ) replace minlib v0.0.0 => ../minlib + replace MINSync v0.0.0 => ../MINSync diff --git a/go.sum b/go.sum index 639531a..ed9078e 100644 --- a/go.sum +++ b/go.sum @@ -88,6 +88,8 @@ github.com/tidwall/tinyqueue v0.1.1/go.mod h1:O/QNHwrnjqr6IHItYrzoHAKYhBkLI67Q09 github.com/tylertreat/BoomFilters v0.0.0-20210315201527-1a82519a3e43 h1:QEePdg0ty2r0t1+qwfZmQ4OOl/MB2UXIeJSpIZv56lg= github.com/tylertreat/BoomFilters v0.0.0-20210315201527-1a82519a3e43/go.mod h1:OYRfF6eb5wY9VRFkXJH8FFBi3plw2v+giaIu7P054pM= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= +github.com/vishalkuo/bimap v0.0.0-20180703190407-09cff2814645 h1:GUsWoxLgZ75MvazbQ0AWSvtjyvhmFryQD7BwWN6+5+0= +github.com/vishalkuo/bimap v0.0.0-20180703190407-09cff2814645/go.mod h1:SLUZBTfsmfFJDSKTVyh/ifAE50/GMATIYGTgr29/2Ms= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zeebo/xxh3 v1.0.1 h1:FMSRIbkrLikb/0hZxmltpg84VkqDAT5M8ufXynuhXsI= github.com/zeebo/xxh3 v1.0.1/go.mod h1:8VHV24/3AZLn3b6Mlp/KuC33LWH687Wq6EnziEB+rsA= diff --git a/utils/NameHelper.go b/utils/NameHelper.go index 4c884a8..5bf2ccf 100644 --- a/utils/NameHelper.go +++ b/utils/NameHelper.go @@ -20,7 +20,9 @@ import "minlib/component" func GetNameComponentPosition(name *component.Identifier, searchString string) int { components := name.GetComponents() for i := 0; i < len(components); i++ { - if components[i].ToUri() == "/"+searchString { + // bug: IdentifierComponent.ToUri() 默认不带斜杠 + // if components[i].ToUri() == "/"+searchString { + if components[i].ToUri() == searchString { return i } }