// Copyright Earl Warren // Copyright Loïc Dachary // SPDX-License-Identifier: MIT package generic import ( "context" "testing" "code.forgejo.org/f3/gof3/v3/f3" "code.forgejo.org/f3/gof3/v3/id" "code.forgejo.org/f3/gof3/v3/kind" "code.forgejo.org/f3/gof3/v3/logger" "code.forgejo.org/f3/gof3/v3/path" "github.com/stretchr/testify/assert" ) type compareFormat struct { f3.Common V int } func (o *compareFormat) Clone() f3.Interface { clone := &compareFormat{} *clone = *o return clone } type compareNodeDriver struct { NullDriver v int ID string } func (o *compareNodeDriver) NewFormat() f3.Interface { return &compareFormat{ Common: f3.NewCommon(o.ID), } } func (o *compareNodeDriver) ToFormat() f3.Interface { f := o.NewFormat().(*compareFormat) f.V = o.v return f } func (o *compareNodeDriver) FromFormat(f f3.Interface) { fc := f.(*compareFormat) o.v = fc.V o.ID = fc.GetID() } func newCompareNodeDriver() NodeDriverInterface { return &compareNodeDriver{} } type compareTreeDriver struct { NullTreeDriver } func newCompareTreeDriver() TreeDriverInterface { return &compareTreeDriver{} } func (o *compareTreeDriver) Factory(ctx context.Context, kind kind.Kind) NodeDriverInterface { d := newCompareNodeDriver() d.SetTreeDriver(o) return d } func newCompareTree() TreeInterface { tree := &testTree{} tree.Init(tree, newTestOptions()) tree.Trace("init done") tree.SetDriver(newCompareTreeDriver()) tree.Register(kindCompareNode, func(ctx context.Context, kind kind.Kind) NodeInterface { node := &compareNode{} return node.Init(node) }) return tree } var kindCompareNode = kind.Kind("compare") type compareNode struct { Node } func TestTreeCompare(t *testing.T) { tree := newTestTree() log := logger.NewCaptureLogger() log.SetLevel(logger.Trace) tree.SetLogger(log) root := tree.Factory(context.Background(), kindTestNodeLevelOne) tree.SetRoot(root) assert.True(t, TreeCompare(context.Background(), tree, path.NewPathFromString(NewElementNode, ""), tree, path.NewPathFromString(NewElementNode, ""))) log.Reset() assert.False(t, TreeCompare(context.Background(), tree, path.NewPathFromString(NewElementNode, "/notfound"), tree, path.NewPathFromString(NewElementNode, ""))) assert.Contains(t, log.String(), "a does not have /notfound") log.Reset() assert.False(t, TreeCompare(context.Background(), tree, path.NewPathFromString(NewElementNode, "/"), tree, path.NewPathFromString(NewElementNode, "/notfound"))) assert.Contains(t, log.String(), "b does not have /notfound") } func TestNodeCompare(t *testing.T) { log := logger.NewCaptureLogger() log.SetLevel(logger.Trace) treeA := newCompareTree() treeA.SetLogger(log) treeB := newCompareTree() treeB.SetLogger(log) nodeA := treeA.Factory(context.Background(), kindCompareNode) nodeA.SetID(id.NewNodeID("root")) assert.True(t, NodeCompare(context.Background(), nodeA, nodeA)) t.Run("different kind", func(t *testing.T) { log.Reset() other := treeB.Factory(context.Background(), kindCompareNode) other.SetKind("other") assert.False(t, NodeCompare(context.Background(), nodeA, other)) assert.Contains(t, log.String(), "kind is different") }) t.Run("difference", func(t *testing.T) { log.Reset() other := treeB.Factory(context.Background(), kindCompareNode) other.FromFormat(&compareFormat{V: 123456}) assert.False(t, NodeCompare(context.Background(), nodeA, other)) assert.Contains(t, log.String(), "difference") assert.Contains(t, log.String(), "123456") }) t.Run("children count", func(t *testing.T) { log.Reset() other := treeB.Factory(context.Background(), kindCompareNode) other.SetChild(treeB.Factory(context.Background(), kindCompareNode)) assert.False(t, NodeCompare(context.Background(), nodeA, other)) assert.Contains(t, log.String(), "children count") }) nodeAA := treeA.Factory(context.Background(), kindCompareNode) nodeAA.SetID(id.NewNodeID("levelone")) nodeA.SetChild(nodeAA) nodeB := treeB.Factory(context.Background(), kindCompareNode) nodeB.SetID(id.NewNodeID("root")) t.Run("children are the same", func(t *testing.T) { nodeBB := treeB.Factory(context.Background(), kindCompareNode) nodeBB.SetID(id.NewNodeID("levelone")) nodeB.SetChild(nodeBB) assert.True(t, NodeCompare(context.Background(), nodeA, nodeB)) nodeB.DeleteChild(nodeBB.GetID()) }) t.Run("children have different IDs", func(t *testing.T) { log.Reset() nodeBB := treeB.Factory(context.Background(), kindCompareNode) nodeBB.SetID(id.NewNodeID("SOMETHINGELSE")) nodeB.SetChild(nodeBB) assert.False(t, NodeCompare(context.Background(), nodeA, nodeB)) assert.Contains(t, log.String(), "id levelone matching the child") nodeB.DeleteChild(nodeBB.GetID()) }) t.Run("children have different content", func(t *testing.T) { log.Reset() nodeBB := treeB.Factory(context.Background(), kindCompareNode) nodeBB.FromFormat(&compareFormat{V: 12345678}) nodeBB.SetID(id.NewNodeID("levelone")) nodeB.SetChild(nodeBB) assert.False(t, NodeCompare(context.Background(), nodeA, nodeB)) assert.Contains(t, log.String(), "difference") assert.Contains(t, log.String(), "12345678") nodeB.DeleteChild(nodeBB.GetID()) }) t.Run("children are the same because of their mapped ID", func(t *testing.T) { log.Reset() nodeBB := treeB.Factory(context.Background(), kindCompareNode) nodeBB.SetID(id.NewNodeID("REMAPPEDID")) nodeB.SetChild(nodeBB) nodeAA.SetMappedID(id.NewNodeID("REMAPPEDID")) assert.True(t, NodeCompare(context.Background(), nodeA, nodeB)) nodeB.DeleteChild(nodeBB.GetID()) nodeAA.SetMappedID(id.NilID) }) t.Run("children are different because of their mapped ID", func(t *testing.T) { log.Reset() nodeBB := treeB.Factory(context.Background(), kindCompareNode) nodeBB.SetID(id.NewNodeID("levelone")) nodeB.SetChild(nodeBB) nodeAA.SetMappedID(id.NewNodeID("REMAPPEDID")) assert.False(t, NodeCompare(context.Background(), nodeA, nodeB)) assert.Contains(t, log.String(), "id REMAPPEDID matching the child") nodeB.DeleteChild(nodeBB.GetID()) nodeAA.SetMappedID(id.NilID) }) }