diff --git a/eacl/filter.go b/eacl/filter.go index 32bfaaa..07eec68 100644 --- a/eacl/filter.go +++ b/eacl/filter.go @@ -174,3 +174,11 @@ func (f *Filter) UnmarshalJSON(data []byte) error { return nil } + +// equalFilters compares Filter with each other. +func equalFilters(f1, f2 Filter) bool { + return f1.From() == f2.From() && + f1.Matcher() == f2.Matcher() && + f1.Key() == f2.Key() && + f1.Value() == f2.Value() +} diff --git a/eacl/record.go b/eacl/record.go index 722a4bc..006198a 100644 --- a/eacl/record.go +++ b/eacl/record.go @@ -267,3 +267,33 @@ func (r *Record) UnmarshalJSON(data []byte) error { return nil } + +// equalRecords compares Record with each other. +func equalRecords(r1, r2 Record) bool { + if r1.Operation() != r2.Operation() || + r1.Action() != r2.Action() { + return false + } + + fs1, fs2 := r1.Filters(), r2.Filters() + ts1, ts2 := r1.Targets(), r2.Targets() + + if len(fs1) != len(fs2) || + len(ts1) != len(ts2) { + return false + } + + for i := 0; i < len(fs1); i++ { + if !equalFilters(fs1[i], fs2[i]) { + return false + } + } + + for i := 0; i < len(ts1); i++ { + if !equalTargets(ts1[i], ts2[i]) { + return false + } + } + + return true +} diff --git a/eacl/table.go b/eacl/table.go index 3ce7d87..555a1d8 100644 --- a/eacl/table.go +++ b/eacl/table.go @@ -1,7 +1,6 @@ package eacl import ( - "bytes" "crypto/sha256" v2acl "github.com/nspcc-dev/neofs-api-go/v2/acl" @@ -201,58 +200,23 @@ func (t *Table) UnmarshalJSON(data []byte) error { return nil } -// EqualTo compares Table between each other. -func (t *Table) EqualTo(table *Table) bool { - if t == nil || table == nil { +// EqualTables compares Table with each other. +func EqualTables(t1, t2 Table) bool { + if !t1.CID().Equal(t2.CID()) || + !t1.Version().Equal(t2.Version()) { return false } - if !t.cid.Equal(table.cid) { + rs1, rs2 := t1.Records(), t2.Records() + + if len(rs1) != len(rs2) { return false } - if len(t.records) != len(table.records) { - return false - } - - for i := 0; i < len(t.records); i++ { - tRec, tableRec := t.records[i], table.records[i] - if tRec.operation != tableRec.operation || - tRec.action != tableRec.action { + for i := 0; i < len(rs1); i++ { + if !equalRecords(rs1[i], rs2[i]) { return false } - - if len(tRec.filters) != len(tableRec.filters) || - len(tRec.targets) != len(tableRec.targets) { - return false - } - - for j := 0; j < len(tRec.filters); j++ { - if tRec.filters[j].from != tableRec.filters[j].from || - tRec.filters[j].matcher != tableRec.filters[j].matcher || - tRec.filters[j].Value() != tableRec.filters[j].Value() || - tRec.filters[j].key.typ != tableRec.filters[j].key.typ || - tRec.filters[j].key.str != tableRec.filters[j].key.str { - return false - } - } - - for j := 0; j < len(tRec.targets); j++ { - if tRec.targets[j].role != tableRec.targets[j].role { - return false - } - - if len(tRec.targets[j].keys) != len(tableRec.targets[j].keys) { - return false - } - - tKeys, tableKeys := tRec.targets[j].keys, tableRec.targets[j].keys - for k := 0; k < len(tKeys); k++ { - if !bytes.Equal(tKeys[k], tableKeys[k]) { - return false - } - } - } } return true diff --git a/eacl/target.go b/eacl/target.go index 8caea1c..84f62c0 100644 --- a/eacl/target.go +++ b/eacl/target.go @@ -1,6 +1,7 @@ package eacl import ( + "bytes" "crypto/ecdsa" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -155,3 +156,24 @@ func (t *Target) UnmarshalJSON(data []byte) error { return nil } + +// equalTargets compares Target with each other. +func equalTargets(t1, t2 Target) bool { + if t1.Role() != t2.Role() { + return false + } + + keys1, keys2 := t1.BinaryKeys(), t2.BinaryKeys() + + if len(keys1) != len(keys2) { + return false + } + + for i := 0; i < len(keys1); i++ { + if !bytes.Equal(keys1[i], keys2[i]) { + return false + } + } + + return true +} diff --git a/eacl/test/benchmark_test.go b/eacl/test/benchmark_test.go index dfc0430..d1bd7c6 100644 --- a/eacl/test/benchmark_test.go +++ b/eacl/test/benchmark_test.go @@ -27,7 +27,7 @@ func baseBenchmarkTableBinaryComparison(b *testing.B, factor int) { } } -func baseBenchmarkTableEqualToComparison(b *testing.B, factor int) { +func baseBenchmarkTableEqualsComparison(b *testing.B, factor int) { t := TableN(factor) data, err := t.Marshal() require.NoError(b, err) @@ -39,7 +39,7 @@ func baseBenchmarkTableEqualToComparison(b *testing.B, factor int) { b.ResetTimer() b.StartTimer() for i := 0; i < b.N; i++ { - if !t.EqualTo(t2) { + if !eacl.EqualTables(*t, *t2) { b.Fail() } } @@ -49,24 +49,24 @@ func BenchmarkTableBinaryComparison(b *testing.B) { baseBenchmarkTableBinaryComparison(b, 1) } -func BenchmarkTableEqualToComparison(b *testing.B) { - baseBenchmarkTableEqualToComparison(b, 1) +func BenchmarkTableEqualsComparison(b *testing.B) { + baseBenchmarkTableEqualsComparison(b, 1) } func BenchmarkTableBinaryComparison10(b *testing.B) { baseBenchmarkTableBinaryComparison(b, 10) } -func BenchmarkTableEqualToComparison10(b *testing.B) { - baseBenchmarkTableEqualToComparison(b, 10) +func BenchmarkTableEqualsComparison10(b *testing.B) { + baseBenchmarkTableEqualsComparison(b, 10) } func BenchmarkTableBinaryComparison100(b *testing.B) { baseBenchmarkTableBinaryComparison(b, 100) } -func BenchmarkTableEqualToComparison100(b *testing.B) { - baseBenchmarkTableEqualToComparison(b, 100) +func BenchmarkTableEqualsComparison100(b *testing.B) { + baseBenchmarkTableEqualsComparison(b, 100) } // Target returns random eacl.Target. diff --git a/pool/pool.go b/pool/pool.go index 7d9350b..51c88ee 100644 --- a/pool/pool.go +++ b/pool/pool.go @@ -1597,7 +1597,7 @@ func waitForEACLPresence(ctx context.Context, pool *Pool, cnrID *cid.ID, table * return waitFor(ctx, waitParams, func(ctx context.Context) bool { eaclTable, err := pool.GetEACL(ctx, prm) if err == nil { - return table.EqualTo(eaclTable) + return eacl.EqualTables(*table, *eaclTable) } return false }) diff --git a/version/version.go b/version/version.go index 071ecba..a1f30ac 100644 --- a/version/version.go +++ b/version/version.go @@ -87,3 +87,9 @@ func (v *Version) MarshalJSON() ([]byte, error) { func (v *Version) UnmarshalJSON(data []byte) error { return (*refs.Version)(v).UnmarshalJSON(data) } + +// Equal returns true if versions are identical. +func (v Version) Equal(v2 Version) bool { + return v.Major() == v2.Major() && + v.Minor() == v2.Minor() +}