diff --git a/pkg/acl/tree/objecttree_test.go b/pkg/acl/tree/objecttree_test.go index 5acfd5be..463dca31 100644 --- a/pkg/acl/tree/objecttree_test.go +++ b/pkg/acl/tree/objecttree_test.go @@ -92,12 +92,13 @@ func prepareTreeContext(t *testing.T, aclList list.ACLList) testTreeContext { treeStorage := changeCreator.createNewTreeStorage("treeId", aclList.ID(), aclList.Head().Id, "0") changeBuilder := &mockChangeBuilder{} deps := objectTreeDeps{ - changeBuilder: changeBuilder, - treeBuilder: newTreeBuilder(treeStorage, changeBuilder), - treeStorage: treeStorage, - updateListener: nil, - validator: &mockChangeValidator{}, - aclList: aclList, + changeBuilder: changeBuilder, + treeBuilder: newTreeBuilder(treeStorage, changeBuilder), + treeStorage: treeStorage, + updateListener: nil, + rawChangeLoader: newRawChangeLoader(treeStorage, changeBuilder), + validator: &mockChangeValidator{}, + aclList: aclList, } // check build @@ -271,7 +272,7 @@ func TestObjectTree(t *testing.T) { assert.Equal(t, true, objTree.(*objectTree).snapshotPathIsActual()) }) - t.Run("changes after common snapshot complex", func(t *testing.T) { + t.Run("changes from tree after common snapshot complex", func(t *testing.T) { ctx := prepareTreeContext(t, aclList) changeCreator := ctx.changeCreator objTree := ctx.objTree @@ -289,7 +290,7 @@ func TestObjectTree(t *testing.T) { require.NoError(t, err, "adding changes should be without error") require.Equal(t, "0", objTree.Root().Id) - t.Run("changes from tree", func(t *testing.T) { + t.Run("all changes from tree", func(t *testing.T) { changes, err := objTree.ChangesAfterCommonSnapshot([]string{"3", "0"}, []string{}) require.NoError(t, err, "changes after common snapshot should be without error") @@ -302,9 +303,11 @@ func TestObjectTree(t *testing.T) { _, ok := changeIds[raw.Id] assert.Equal(t, true, ok) } + _, ok := changeIds["0"] + assert.Equal(t, true, ok) }) - t.Run("changes from tree after first", func(t *testing.T) { + t.Run("changes from tree after 1", func(t *testing.T) { changes, err := objTree.ChangesAfterCommonSnapshot([]string{"3", "0"}, []string{"1"}) require.NoError(t, err, "changes after common snapshot should be without error") @@ -313,15 +316,33 @@ func TestObjectTree(t *testing.T) { changeIds[ch.Id] = struct{}{} } - for _, raw := range rawChanges { - if raw.Id == "1" { - _, ok := changeIds[raw.Id] - assert.Equal(t, false, ok) - continue - } - _, ok := changeIds[raw.Id] + for _, id := range []string{"2", "3", "4", "5", "6"} { + _, ok := changeIds[id] assert.Equal(t, true, ok) } + for _, id := range []string{"0", "1"} { + _, ok := changeIds[id] + assert.Equal(t, false, ok) + } + }) + + t.Run("changes from tree after 5", func(t *testing.T) { + changes, err := objTree.ChangesAfterCommonSnapshot([]string{"3", "0"}, []string{"5"}) + require.NoError(t, err, "changes after common snapshot should be without error") + + changeIds := make(map[string]struct{}) + for _, ch := range changes { + changeIds[ch.Id] = struct{}{} + } + + for _, id := range []string{"2", "3", "4", "6"} { + _, ok := changeIds[id] + assert.Equal(t, true, ok) + } + for _, id := range []string{"0", "1", "5"} { + _, ok := changeIds[id] + assert.Equal(t, false, ok) + } }) }) diff --git a/pkg/acl/tree/rawloader.go b/pkg/acl/tree/rawloader.go index 27cb7ba7..0c1956a9 100644 --- a/pkg/acl/tree/rawloader.go +++ b/pkg/acl/tree/rawloader.go @@ -90,7 +90,7 @@ func (r *rawChangeLoader) LoadFromTree(t *Tree, breakpoints []string) ([]*aclpb. return true }, func(visited []*Change) { - discardFromSlice(results, func(change *Change) bool { + results = discardFromSlice(results, func(change *Change) bool { return change.visited }) }, @@ -200,7 +200,7 @@ func (r *rawChangeLoader) LoadFromStorage(commonSnapshot string, heads, breakpoi }) // discarding visited - discardFromSlice(buffer, func(change *aclpb.RawChange) bool { + buffer = discardFromSlice(buffer, func(change *aclpb.RawChange) bool { return change == nil }) @@ -233,17 +233,20 @@ func (r *rawChangeLoader) loadEntry(id string) (entry rawCacheEntry, err error) return } -func discardFromSlice[T any](elements []T, isDiscarded func(T) bool) { +func discardFromSlice[T any](elements []T, isDiscarded func(T) bool) []T { var ( finishedIdx = 0 currentIdx = 0 ) for currentIdx < len(elements) { - if !isDiscarded(elements[currentIdx]) && finishedIdx != currentIdx { - elements[finishedIdx] = elements[currentIdx] + if !isDiscarded(elements[currentIdx]) { + if finishedIdx != currentIdx { + elements[finishedIdx] = elements[currentIdx] + } finishedIdx++ } currentIdx++ } elements = elements[:finishedIdx] + return elements } diff --git a/pkg/acl/tree/treebuilder.go b/pkg/acl/tree/treebuilder.go index c88324b3..fdf69873 100644 --- a/pkg/acl/tree/treebuilder.go +++ b/pkg/acl/tree/treebuilder.go @@ -73,22 +73,24 @@ func (tb *treeBuilder) buildTree(heads []string, breakpoint string) (err error) return } tb.tree.AddFast(ch) - changes, err := tb.dfs(heads, breakpoint, tb.loadChange) + changes, err := tb.dfs(heads, breakpoint) tb.tree.AddFast(changes...) return } -func (tb *treeBuilder) dfs( - heads []string, - breakpoint string, - load func(string) (*Change, error)) (buf []*Change, err error) { +func (tb *treeBuilder) dfs(heads []string, breakpoint string) (buf []*Change, err error) { + // initializing buffers tb.idStack = tb.idStack[:0] tb.loadBuffer = tb.loadBuffer[:0] + // updating map uniqMap := map[string]struct{}{breakpoint: {}} + + // preparing dfs tb.idStack = append(tb.idStack, heads...) + // dfs for len(tb.idStack) > 0 { id := tb.idStack[len(tb.idStack)-1] tb.idStack = tb.idStack[:len(tb.idStack)-1] @@ -96,7 +98,7 @@ func (tb *treeBuilder) dfs( continue } - ch, err := load(id) + ch, err := tb.loadChange(id) if err != nil { continue }