Repository: etcd-io/etcd
File: tests/e2e/v2store_deprecation_test.go (Go)

Code before:

func assertV2StoreMembershipEqual(tb testing.TB, lg *zap.Logger, firstSnapPath, secondSnapPath string) {
	st1 := loadV2StoreData(tb, lg, firstSnapPath)
	st2 := loadV2StoreData(tb, lg, secondSnapPath)

	st1Members, st1Deleted := membership.MembersFromStore(lg, st1)
	st2Members, st2Deleted := membership.MembersFromStore(lg, st2)

	require.Lenf(tb, st1Members, len(st2Members), "number of members in v2 store do not match")
	require.Lenf(tb, st1Deleted, len(st2Deleted), "number of deleted members in v2 store do not match")

	// rebuild ID because original ID was generated from hash of peerURLs + clusterName + time
	require.Equal(tb, rebuildMemberIDs(tb, st1Members), rebuildMemberIDs(tb, st2Members))
}

// loadV2StoreData reads v2 store from the snapshot file at fpath.
func loadV2StoreData(tb testing.TB, lg *zap.Logger, fpath string) v2store.Store {
	sn, err := snap.Read(lg, fpath)
	require.NoError(tb, err)

	v2data := v2store.New(etcdserver.StoreClusterPrefix, etcdserver.StoreKeysPrefix)
	v2data.Recovery(sn.Data)
	return v2data
}

func rebuildMemberIDs(tb testing.TB, members map[types.ID]*membership.Member) map[types.ID]*membership.Member {
	newMembers := make(map[types.ID]*membership.Member)
	for _, m := range members {
		var newID types.ID
		peerURLs, err := types.NewURLs(m.PeerURLs)
		require.NoError(tb, err)

		if m.IsLearner {
			newID = membership.NewMemberAsLearner(m.Name, peerURLs, "cluster", nil).ID
		} else {
			newID = membership.NewMember(m.Name, peerURLs, "cluster", nil).ID
		}
		m.ID = newID
		newMembers[newID] = m
	}
	return newMembers
}


Review comment (suggestion):
Maybe we could just drop ID and URL when comparing members? At some point we are just comparing number of members and number of learners. It 

Code after:

func assertV2StoreMembershipEqual(tb testing.TB, lg *zap.Logger, firstSnapPath, secondSnapPath string) {
	st1 := loadV2StoreData(tb, lg, firstSnapPath)
	st2 := loadV2StoreData(tb, lg, secondSnapPath)

	st1Members, st1Deleted := membership.MembersFromStore(lg, st1)
	st2Members, st2Deleted := membership.MembersFromStore(lg, st2)

	require.Lenf(tb, st1Members, len(st2Members), "number of members in v2 store do not match")
	require.NotEmptyf(tb, st1Members, "no members found in v2 store")
	require.Lenf(tb, st1Deleted, len(st2Deleted), "number of deleted members in v2 store do not match")

	// remove ID because original ID was generated from hash of peerURLs + clusterName + time
	require.Equal(tb, rebuildMembers(tb, st1Members), rebuildMembers(tb, st2Members))
}

// loadV2StoreData reads v2 store from the snapshot file at fpath.
func loadV2StoreData(tb testing.TB, lg *zap.Logger, fpath string) v2store.Store {
	sn, err := snap.Read(lg, fpath)
	require.NoError(tb, err)

	v2data := v2store.New(etcdserver.StoreClusterPrefix, etcdserver.StoreKeysPrefix)
	v2data.Recovery(sn.Data)
	return v2data
}

// rebuildMembers rebuilds the members map with zeroed IDs and peerURLs as keys.
func rebuildMembers(tb testing.TB, members map[types.ID]*membership.Member) map[string]*membership.Member {
	newMembers := make(map[string]*membership.Member)
	for _, m := range members {
		peerURLs, err := types.NewURLs(m.PeerURLs)
		require.NoError(tb, err)

		m.ID = 0
		newMembers[peerURLs.String()] = m
	}
	return newMembers
}