From d568458fabee05dcf04cd0a39ba067e609085940 Mon Sep 17 00:00:00 2001 From: Denis Kirillov Date: Fri, 18 Mar 2022 13:25:05 +0300 Subject: [PATCH] [#180] eacl: add EqualTo for table Signed-off-by: Denis Kirillov --- eacl/table.go | 58 ++++++++++++++++++ eacl/test/benchmark_test.go | 116 ++++++++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+) create mode 100644 eacl/test/benchmark_test.go diff --git a/eacl/table.go b/eacl/table.go index 0397b166..3ce7d876 100644 --- a/eacl/table.go +++ b/eacl/table.go @@ -1,6 +1,7 @@ package eacl import ( + "bytes" "crypto/sha256" v2acl "github.com/nspcc-dev/neofs-api-go/v2/acl" @@ -199,3 +200,60 @@ 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 { + return false + } + + if !t.cid.Equal(table.cid) { + 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 { + 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/test/benchmark_test.go b/eacl/test/benchmark_test.go new file mode 100644 index 00000000..dfc04303 --- /dev/null +++ b/eacl/test/benchmark_test.go @@ -0,0 +1,116 @@ +package eacltest + +import ( + "bytes" + "math/rand" + "testing" + + cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test" + "github.com/nspcc-dev/neofs-sdk-go/eacl" + versiontest "github.com/nspcc-dev/neofs-sdk-go/version/test" + "github.com/stretchr/testify/require" +) + +func baseBenchmarkTableBinaryComparison(b *testing.B, factor int) { + t := TableN(factor) + exp, err := t.Marshal() + require.NoError(b, err) + + b.StopTimer() + b.ResetTimer() + b.StartTimer() + for i := 0; i < b.N; i++ { + got, _ := t.Marshal() + if !bytes.Equal(exp, got) { + b.Fail() + } + } +} + +func baseBenchmarkTableEqualToComparison(b *testing.B, factor int) { + t := TableN(factor) + data, err := t.Marshal() + require.NoError(b, err) + t2 := eacl.NewTable() + err = t2.Unmarshal(data) + require.NoError(b, err) + + b.StopTimer() + b.ResetTimer() + b.StartTimer() + for i := 0; i < b.N; i++ { + if !t.EqualTo(t2) { + b.Fail() + } + } +} + +func BenchmarkTableBinaryComparison(b *testing.B) { + baseBenchmarkTableBinaryComparison(b, 1) +} + +func BenchmarkTableEqualToComparison(b *testing.B) { + baseBenchmarkTableEqualToComparison(b, 1) +} + +func BenchmarkTableBinaryComparison10(b *testing.B) { + baseBenchmarkTableBinaryComparison(b, 10) +} + +func BenchmarkTableEqualToComparison10(b *testing.B) { + baseBenchmarkTableEqualToComparison(b, 10) +} + +func BenchmarkTableBinaryComparison100(b *testing.B) { + baseBenchmarkTableBinaryComparison(b, 100) +} + +func BenchmarkTableEqualToComparison100(b *testing.B) { + baseBenchmarkTableEqualToComparison(b, 100) +} + +// Target returns random eacl.Target. +func TargetN(n int) *eacl.Target { + x := eacl.NewTarget() + + x.SetRole(eacl.RoleSystem) + keys := make([][]byte, n) + + for i := 0; i < n; i++ { + keys[i] = make([]byte, 32) + rand.Read(keys[i]) + } + + x.SetBinaryKeys(keys) + + return x +} + +// Record returns random eacl.Record. +func RecordN(n int) *eacl.Record { + x := eacl.NewRecord() + + x.SetAction(eacl.ActionAllow) + x.SetOperation(eacl.OperationRangeHash) + x.SetTargets(*TargetN(n)) + + for i := 0; i < n; i++ { + x.AddFilter(eacl.HeaderFromObject, eacl.MatchStringEqual, "", cidtest.ID().String()) + } + + return x +} + +func TableN(n int) *eacl.Table { + x := eacl.NewTable() + + x.SetCID(cidtest.ID()) + + for i := 0; i < n; i++ { + x.AddRecord(RecordN(n)) + } + + x.SetVersion(*versiontest.Version()) + + return x +}