[#170] audit: Refactor and document package functionality

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
Leonard Lyubich 2022-03-14 14:30:07 +03:00 committed by Alex Vanin
parent 48150852f3
commit 7d31de57ec
5 changed files with 458 additions and 362 deletions

24
audit/doc.go Normal file
View file

@ -0,0 +1,24 @@
/*
Package audit provides features to process data audit in NeoFS system.
Result type groups values which can be gathered during data audit process:
var res audit.Result
res.ForEpoch(32)
res.ForContainer(cnr)
// ...
res.Complete()
Result instances can be stored in a binary format. On reporter side:
data := res.Marshal()
// send data
On receiver side:
var res audit.Result
err := res.Unmarshal(data)
// ...
Using package types in an application is recommended to potentially work with
different protocol versions with which these types are compatible.
*/
package audit

View file

@ -2,290 +2,316 @@ package audit
import (
"github.com/nspcc-dev/neofs-api-go/v2/audit"
"github.com/nspcc-dev/neofs-api-go/v2/refs"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
"github.com/nspcc-dev/neofs-sdk-go/version"
)
// Result represents v2-compatible data audit result.
type Result audit.DataAuditResult
// NewFromV2 wraps v2 DataAuditResult message to Result.
// Result represents report on the results of the data audit in NeoFS system.
//
// Nil audit.DataAuditResult converts to nil.
func NewResultFromV2(aV2 *audit.DataAuditResult) *Result {
return (*Result)(aV2)
}
// New creates and initializes blank Result.
// Result is mutually binary-compatible with github.com/nspcc-dev/neofs-api-go/v2/audit.DataAuditResult
// message. See Marshal / Unmarshal methods.
//
// Defaults:
// - version: version.Current();
// - complete: false;
// - cid: nil;
// - pubKey: nil;
// - passSG, failSG: nil;
// - failNodes, passNodes: nil;
// - hit, miss, fail: 0;
// - requests, retries: 0;
// - auditEpoch: 0.
func NewResult() *Result {
r := NewResultFromV2(new(audit.DataAuditResult))
r.SetVersion(version.Current())
// Instances can be created using built-in var declaration.
type Result struct {
versionEncoded bool
return r
v2 audit.DataAuditResult
}
// ToV2 converts Result to v2 DataAuditResult message.
// Marshal encodes Result into a canonical NeoFS binary format (Protocol Buffers
// with direct field order).
//
// Nil Result converts to nil.
func (r *Result) ToV2() *audit.DataAuditResult {
return (*audit.DataAuditResult)(r)
// Writes version.Current() protocol version into the resulting message if Result
// hasn't been already decoded from such a message using Unmarshal.
//
// See also Unmarshal.
func (r *Result) Marshal() []byte {
if !r.versionEncoded {
r.v2.SetVersion(version.Current().ToV2())
r.versionEncoded = true
}
// Marshal marshals Result into a protobuf binary form.
func (r *Result) Marshal() ([]byte, error) {
return (*audit.DataAuditResult)(r).StableMarshal(nil)
data, err := r.v2.StableMarshal(nil)
if err != nil {
panic(err)
}
// Unmarshal unmarshals protobuf binary representation of Result.
return data
}
// Unmarshal decodes Result from its canonical NeoFS binary format (Protocol Buffers
// with direct field order). Returns an error describing a format violation.
//
// See also Marshal.
func (r *Result) Unmarshal(data []byte) error {
return (*audit.DataAuditResult)(r).Unmarshal(data)
err := r.v2.Unmarshal(data)
if err == nil {
r.versionEncoded = true
}
// MarshalJSON encodes Result to protobuf JSON format.
func (r *Result) MarshalJSON() ([]byte, error) {
return (*audit.DataAuditResult)(r).MarshalJSON()
return err
}
// UnmarshalJSON decodes Result from protobuf JSON format.
func (r *Result) UnmarshalJSON(data []byte) error {
return (*audit.DataAuditResult)(r).UnmarshalJSON(data)
// Epoch returns NeoFS epoch when the data associated with the Result was audited.
//
// Zero Result has zero epoch.
//
// See also ForEpoch.
func (r Result) Epoch() uint64 {
return r.v2.GetAuditEpoch()
}
// Version returns Data Audit structure version.
func (r *Result) Version() *version.Version {
return version.NewFromV2(
(*audit.DataAuditResult)(r).GetVersion())
// ForEpoch specifies NeoFS epoch when the data associated with the Result was audited.
//
// See also Epoch.
func (r *Result) ForEpoch(epoch uint64) {
r.v2.SetAuditEpoch(epoch)
}
// SetVersion sets Data Audit structure version.
func (r *Result) SetVersion(v *version.Version) {
(*audit.DataAuditResult)(r).SetVersion(v.ToV2())
// Container returns identifier of the container with which the data audit Result
// is associated.
//
// Returns nil if container is not specified. Zero Result has nil container.
// Return value MUST NOT be mutated: to do this, first make a copy.
//
// See also ForContainer.
func (r Result) Container() *cid.ID {
return cid.NewFromV2(r.v2.GetContainerID())
}
// AuditEpoch returns epoch number when the Data Audit was conducted.
func (r *Result) AuditEpoch() uint64 {
return (*audit.DataAuditResult)(r).GetAuditEpoch()
// ForContainer returns identifier of the container with which the data audit Result
// is associated.
//
// See also Container.
func (r *Result) ForContainer(cnr cid.ID) {
r.v2.SetContainerID(cnr.ToV2())
}
// SetAuditEpoch sets epoch number when the Data Audit was conducted.
func (r *Result) SetAuditEpoch(epoch uint64) {
(*audit.DataAuditResult)(r).SetAuditEpoch(epoch)
// AuditorKey returns public key of the auditing NeoFS Inner Ring node in
// a NeoFS binary key format.
//
// Zero Result has nil key. Return value MUST NOT be mutated: to do this,
// first make a copy.
//
// See also SetAuditorPublicKey.
func (r Result) AuditorKey() []byte {
return r.v2.GetPublicKey()
}
// ContainerID returns container under audit.
func (r *Result) ContainerID() *cid.ID {
return cid.NewFromV2(
(*audit.DataAuditResult)(r).GetContainerID())
// SetAuditorKey specifies public key of the auditing NeoFS Inner Ring node in
// a NeoFS binary key format.
//
// Argument MUST NOT be mutated at least until the end of using the Result.
//
// See also AuditorKey.
func (r *Result) SetAuditorKey(key []byte) {
r.v2.SetPublicKey(key)
}
// SetContainerID sets container under audit.
func (r *Result) SetContainerID(id *cid.ID) {
(*audit.DataAuditResult)(r).SetContainerID(id.ToV2())
// Completed returns completion state of the data audit associated with the Result.
//
// Zero Result corresponds to incomplete data audit.
//
// See also Complete.
func (r Result) Completed() bool {
return r.v2.GetComplete()
}
// PublicKey returns public key of the auditing InnerRing node in a binary format.
func (r *Result) PublicKey() []byte {
return (*audit.DataAuditResult)(r).GetPublicKey()
// Complete marks the data audit associated with the Result as completed.
//
// See also Completed.
func (r *Result) Complete() {
r.v2.SetComplete(true)
}
// SetPublicKey sets public key of the auditing InnerRing node in a binary format.
func (r *Result) SetPublicKey(key []byte) {
(*audit.DataAuditResult)(r).SetPublicKey(key)
// RequestsPoR returns number of requests made by Proof-of-Retrievability
// audit check to get all headers of the objects inside storage groups.
//
// Zero Result has zero requests.
//
// See also SetRequestsPoR.
func (r Result) RequestsPoR() uint32 {
return r.v2.GetRequests()
}
// Complete returns completion state of audit result.
func (r *Result) Complete() bool {
return (*audit.DataAuditResult)(r).GetComplete()
// SetRequestsPoR sets number of requests made by Proof-of-Retrievability
// audit check to get all headers of the objects inside storage groups.
//
// See also RequestsPoR.
func (r *Result) SetRequestsPoR(v uint32) {
r.v2.SetRequests(v)
}
// SetComplete sets completion state of audit result.
func (r *Result) SetComplete(v bool) {
(*audit.DataAuditResult)(r).SetComplete(v)
// RetriesPoR returns number of retries made by Proof-of-Retrievability
// audit check to get all headers of the objects inside storage groups.
//
// Zero Result has zero retries.
//
// See also SetRetriesPoR.
func (r Result) RetriesPoR() uint32 {
return r.v2.GetRetries()
}
// Requests returns number of requests made by PoR audit check to get
// all headers of the objects inside storage groups.
func (r *Result) Requests() uint32 {
return (*audit.DataAuditResult)(r).GetRequests()
// SetRetriesPoR sets number of retries made by Proof-of-Retrievability
// audit check to get all headers of the objects inside storage groups.
//
// See also RetriesPoR.
func (r *Result) SetRetriesPoR(v uint32) {
r.v2.SetRetries(v)
}
// SetRequests sets number of requests made by PoR audit check to get
// all headers of the objects inside storage groups.
func (r *Result) SetRequests(v uint32) {
(*audit.DataAuditResult)(r).SetRequests(v)
// IteratePassedStorageGroups iterates over all storage groups that passed
// Proof-of-Retrievability audit check and passes them into f. Breaks on f's
// false return, f MUST NOT be nil.
//
// Zero Result has no passed storage groups and doesn't call f.
//
// See also SubmitPassedStorageGroup.
func (r Result) IteratePassedStorageGroups(f func(oid.ID) bool) {
r2 := r.v2.GetPassSG()
for i := range r2 {
if !f(*oid.NewIDFromV2(&r2[i])) {
return
}
// Retries returns number of retries made by PoR audit check to get
// all headers of the objects inside storage groups.
func (r *Result) Retries() uint32 {
return (*audit.DataAuditResult)(r).GetRetries()
}
// SetRetries sets number of retries made by PoR audit check to get
// all headers of the objects inside storage groups.
func (r *Result) SetRetries(v uint32) {
(*audit.DataAuditResult)(r).SetRetries(v)
}
// PassSG returns list of Storage Groups that passed audit PoR stage.
func (r *Result) PassSG() []oid.ID {
mV2 := (*audit.DataAuditResult)(r).
GetPassSG()
if mV2 == nil {
return nil
}
m := make([]oid.ID, len(mV2))
for i := range mV2 {
m[i] = *oid.NewIDFromV2(&mV2[i])
}
return m
}
// SetPassSG sets list of Storage Groups that passed audit PoR stage.
func (r *Result) SetPassSG(list []oid.ID) {
mV2 := (*audit.DataAuditResult)(r).
GetPassSG()
if list == nil {
mV2 = nil
} else {
ln := len(list)
if cap(mV2) >= ln {
mV2 = mV2[:0]
} else {
mV2 = make([]refs.ObjectID, ln)
}
for i := 0; i < ln; i++ {
mV2[i] = *list[i].ToV2()
}
}
(*audit.DataAuditResult)(r).SetPassSG(mV2)
// SubmitPassedStorageGroup marks storage group as passed Proof-of-Retrievability
// audit check.
//
// See also IteratePassedStorageGroups.
func (r *Result) SubmitPassedStorageGroup(sg oid.ID) {
r.v2.SetPassSG(append(r.v2.GetPassSG(), *sg.ToV2()))
}
// FailSG returns list of Storage Groups that failed audit PoR stage.
func (r *Result) FailSG() []oid.ID {
mV2 := (*audit.DataAuditResult)(r).
GetFailSG()
// IterateFailedStorageGroups is similar to IteratePassedStorageGroups but for failed groups.
//
// See also SubmitFailedStorageGroup.
func (r Result) IterateFailedStorageGroups(f func(oid.ID) bool) {
v := r.v2.GetFailSG()
if mV2 == nil {
return nil
for i := range v {
if !f(*oid.NewIDFromV2(&v[i])) {
return
}
m := make([]oid.ID, len(mV2))
for i := range mV2 {
m[i] = *oid.NewIDFromV2(&mV2[i])
}
return m
}
// SetFailSG sets list of Storage Groups that failed audit PoR stage.
func (r *Result) SetFailSG(list []oid.ID) {
mV2 := (*audit.DataAuditResult)(r).
GetFailSG()
if list == nil {
mV2 = nil
} else {
ln := len(list)
if cap(mV2) >= ln {
mV2 = mV2[:0]
} else {
mV2 = make([]refs.ObjectID, ln)
}
for i := 0; i < ln; i++ {
mV2[i] = *list[i].ToV2()
}
}
(*audit.DataAuditResult)(r).SetFailSG(mV2)
// SubmitFailedStorageGroup is similar to SubmitPassedStorageGroup but for failed groups.
//
// See also IterateFailedStorageGroups.
func (r *Result) SubmitFailedStorageGroup(sg oid.ID) {
r.v2.SetFailSG(append(r.v2.GetFailSG(), *sg.ToV2()))
}
// Hit returns number of sampled objects under audit placed
// Hits returns number of sampled objects under audit placed
// in an optimal way according to the container's placement policy
// when checking Proof-of-Placement.
//
// Zero result has zero hits.
//
// See also SetHits.
func (r Result) Hits() uint32 {
return r.v2.GetHit()
}
// SetHits sets number of sampled objects under audit placed
// in an optimal way according to the containers placement policy
// when checking PoP.
func (r *Result) Hit() uint32 {
return (*audit.DataAuditResult)(r).GetHit()
// when checking Proof-of-Placement.
//
// See also Hits.
func (r *Result) SetHits(hit uint32) {
r.v2.SetHit(hit)
}
// SetHit sets number of sampled objects under audit placed
// in an optimal way according to the containers placement policy
// when checking PoP.
func (r *Result) SetHit(hit uint32) {
(*audit.DataAuditResult)(r).SetHit(hit)
// Misses returns number of sampled objects under audit placed
// in suboptimal way according to the container's placement policy,
// but still at a satisfactory level when checking Proof-of-Placement.
//
// Zero Result has zero misses.
//
// See also SetMisses.
func (r Result) Misses() uint32 {
return r.v2.GetMiss()
}
// Miss returns number of sampled objects under audit placed
// in suboptimal way according to the containers placement policy,
// but still at a satisfactory level when checking PoP.
func (r *Result) Miss() uint32 {
return (*audit.DataAuditResult)(r).GetMiss()
// SetMisses sets number of sampled objects under audit placed
// in suboptimal way according to the container's placement policy,
// but still at a satisfactory level when checking Proof-of-Placement.
//
// See also Misses.
func (r *Result) SetMisses(miss uint32) {
r.v2.SetMiss(miss)
}
// SetMiss sets number of sampled objects under audit placed
// in suboptimal way according to the containers placement policy,
// but still at a satisfactory level when checking PoP.
func (r *Result) SetMiss(miss uint32) {
(*audit.DataAuditResult)(r).SetMiss(miss)
}
// Fail returns number of sampled objects under audit stored
// Failures returns number of sampled objects under audit stored
// in a way not confirming placement policy or not found at all
// when checking PoP.
func (r *Result) Fail() uint32 {
return (*audit.DataAuditResult)(r).GetFail()
// when checking Proof-of-Placement.
//
// Zero result has zero failures.
//
// See also SetFailures.
func (r Result) Failures() uint32 {
return r.v2.GetFail()
}
// SetFail sets number of sampled objects under audit stored
// SetFailures sets number of sampled objects under audit stored
// in a way not confirming placement policy or not found at all
// when checking PoP.
func (r *Result) SetFail(fail uint32) {
(*audit.DataAuditResult)(r).SetFail(fail)
// when checking Proof-of-Placement.
//
// See also Failures.
func (r *Result) SetFailures(fail uint32) {
r.v2.SetFail(fail)
}
// PassNodes returns list of storage node public keys that
// passed at least one PDP.
func (r *Result) PassNodes() [][]byte {
return (*audit.DataAuditResult)(r).GetPassNodes()
// IteratePassedStorageNodes iterates over all storage nodes that passed at least one
// Proof-of-Data-Possession audit check and passes their public keys into f. Breaks on
// f's false return.
//
// f MUST NOT be nil and MUST NOT mutate parameter passed into it at least until
// the end of using the Result.
//
// Zero Result has no passed storage nodes and doesn't call f.
//
// See also SubmitPassedStorageNode.
func (r Result) IteratePassedStorageNodes(f func([]byte) bool) {
v := r.v2.GetPassNodes()
for i := range v {
if !f(v[i]) {
return
}
}
}
// SetPassNodes sets list of storage node public keys that
// passed at least one PDP.
func (r *Result) SetPassNodes(list [][]byte) {
(*audit.DataAuditResult)(r).SetPassNodes(list)
// SubmitPassedStorageNodes marks storage node list as passed Proof-of-Data-Possession
// audit check. The list contains public keys.
//
// Argument and its elements MUST NOT be mutated at least until the end of using the Result.
//
// See also IteratePassedStorageNodes.
func (r *Result) SubmitPassedStorageNodes(list [][]byte) {
r.v2.SetPassNodes(list)
}
// FailNodes returns list of storage node public keys that
// failed at least one PDP.
func (r *Result) FailNodes() [][]byte {
return (*audit.DataAuditResult)(r).GetFailNodes()
// IterateFailedStorageNodes is similar to IteratePassedStorageNodes but for failed nodes.
//
// See also SubmitPassedStorageNodes.
func (r Result) IterateFailedStorageNodes(f func([]byte) bool) {
v := r.v2.GetFailNodes()
for i := range v {
if !f(v[i]) {
return
}
}
}
// SetFailNodes sets list of storage node public keys that
// failed at least one PDP.
func (r *Result) SetFailNodes(list [][]byte) {
(*audit.DataAuditResult)(r).SetFailNodes(list)
// SubmitFailedStorageNodes is similar to SubmitPassedStorageNodes but for failed nodes.
//
// See also IterateFailedStorageNodes.
func (r *Result) SubmitFailedStorageNodes(list [][]byte) {
r.v2.SetFailNodes(list)
}

View file

@ -1,154 +1,188 @@
package audit_test
import (
"bytes"
"testing"
auditv2 "github.com/nspcc-dev/neofs-api-go/v2/audit"
"github.com/nspcc-dev/neofs-sdk-go/audit"
audittest "github.com/nspcc-dev/neofs-sdk-go/audit/test"
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
oidtest "github.com/nspcc-dev/neofs-sdk-go/object/id/test"
"github.com/nspcc-dev/neofs-sdk-go/version"
"github.com/stretchr/testify/require"
)
func TestResult(t *testing.T) {
r := audit.NewResult()
require.Equal(t, version.Current(), r.Version())
func TestResultData(t *testing.T) {
var r audit.Result
epoch := uint64(13)
r.SetAuditEpoch(epoch)
require.Equal(t, epoch, r.AuditEpoch())
countSG := func(passed bool, f func(oid.ID)) int {
called := 0
cid := cidtest.ID()
r.SetContainerID(cid)
require.Equal(t, cid, r.ContainerID())
ff := func(arg oid.ID) bool {
called++
key := []byte{1, 2, 3}
r.SetPublicKey(key)
require.Equal(t, key, r.PublicKey())
r.SetComplete(true)
require.True(t, r.Complete())
requests := uint32(2)
r.SetRequests(requests)
require.Equal(t, requests, r.Requests())
retries := uint32(1)
r.SetRetries(retries)
require.Equal(t, retries, r.Retries())
passSG := []oid.ID{*oidtest.ID(), *oidtest.ID()}
r.SetPassSG(passSG)
require.Equal(t, passSG, r.PassSG())
failSG := []oid.ID{*oidtest.ID(), *oidtest.ID()}
r.SetFailSG(failSG)
require.Equal(t, failSG, r.FailSG())
hit := uint32(1)
r.SetHit(hit)
require.Equal(t, hit, r.Hit())
miss := uint32(2)
r.SetMiss(miss)
require.Equal(t, miss, r.Miss())
fail := uint32(3)
r.SetFail(fail)
require.Equal(t, fail, r.Fail())
passNodes := [][]byte{{1}, {2}}
r.SetPassNodes(passNodes)
require.Equal(t, passNodes, r.PassNodes())
failNodes := [][]byte{{3}, {4}}
r.SetFailNodes(failNodes)
require.Equal(t, failNodes, r.FailNodes())
if f != nil {
f(arg)
}
func TestStorageGroupEncoding(t *testing.T) {
r := audittest.Result()
return true
}
if passed {
r.IteratePassedStorageGroups(ff)
} else {
r.IterateFailedStorageGroups(ff)
}
return called
}
countPassSG := func(f func(oid.ID)) int { return countSG(true, f) }
countFailSG := func(f func(oid.ID)) int { return countSG(false, f) }
countNodes := func(passed bool, f func([]byte)) int {
called := 0
ff := func(arg []byte) bool {
called++
if f != nil {
f(arg)
}
return true
}
if passed {
r.IteratePassedStorageNodes(ff)
} else {
r.IterateFailedStorageNodes(ff)
}
return called
}
countPassNodes := func(f func([]byte)) int { return countNodes(true, f) }
countFailNodes := func(f func([]byte)) int { return countNodes(false, f) }
require.Zero(t, r.Epoch())
require.Nil(t, r.Container())
require.Nil(t, r.AuditorKey())
require.False(t, r.Completed())
require.Zero(t, r.RequestsPoR())
require.Zero(t, r.RetriesPoR())
require.Zero(t, countPassSG(nil))
require.Zero(t, countFailSG(nil))
require.Zero(t, countPassNodes(nil))
require.Zero(t, countFailNodes(nil))
epoch := uint64(13)
r.ForEpoch(epoch)
require.Equal(t, epoch, r.Epoch())
cnr := cidtest.ID()
r.ForContainer(*cnr)
require.Equal(t, cnr, r.Container())
key := []byte{1, 2, 3}
r.SetAuditorKey(key)
require.Equal(t, key, r.AuditorKey())
r.Complete()
require.True(t, r.Completed())
requests := uint32(2)
r.SetRequestsPoR(requests)
require.Equal(t, requests, r.RequestsPoR())
retries := uint32(1)
r.SetRetriesPoR(retries)
require.Equal(t, retries, r.RetriesPoR())
passSG1, passSG2 := *oidtest.ID(), *oidtest.ID()
r.SubmitPassedStorageGroup(passSG1)
r.SubmitPassedStorageGroup(passSG2)
called1, called2 := false, false
require.EqualValues(t, 2, countPassSG(func(id oid.ID) {
if id.Equal(&passSG1) {
called1 = true
} else if id.Equal(&passSG2) {
called2 = true
}
}))
require.True(t, called1)
require.True(t, called2)
failSG1, failSG2 := *oidtest.ID(), *oidtest.ID()
r.SubmitFailedStorageGroup(failSG1)
r.SubmitFailedStorageGroup(failSG2)
called1, called2 = false, false
require.EqualValues(t, 2, countFailSG(func(id oid.ID) {
if id.Equal(&failSG1) {
called1 = true
} else if id.Equal(&failSG2) {
called2 = true
}
}))
require.True(t, called1)
require.True(t, called2)
hit := uint32(1)
r.SetHits(hit)
require.Equal(t, hit, r.Hits())
miss := uint32(2)
r.SetMisses(miss)
require.Equal(t, miss, r.Misses())
fail := uint32(3)
r.SetFailures(fail)
require.Equal(t, fail, r.Failures())
passNodes := [][]byte{{1}, {2}}
r.SubmitPassedStorageNodes(passNodes)
called1, called2 = false, false
require.EqualValues(t, 2, countPassNodes(func(arg []byte) {
if bytes.Equal(arg, passNodes[0]) {
called1 = true
} else if bytes.Equal(arg, passNodes[1]) {
called2 = true
}
}))
require.True(t, called1)
require.True(t, called2)
failNodes := [][]byte{{3}, {4}}
r.SubmitFailedStorageNodes(failNodes)
called1, called2 = false, false
require.EqualValues(t, 2, countFailNodes(func(arg []byte) {
if bytes.Equal(arg, failNodes[0]) {
called1 = true
} else if bytes.Equal(arg, failNodes[1]) {
called2 = true
}
}))
require.True(t, called1)
require.True(t, called2)
}
func TestResultEncoding(t *testing.T) {
r := *audittest.Result()
t.Run("binary", func(t *testing.T) {
data, err := r.Marshal()
require.NoError(t, err)
data := r.Marshal()
r2 := audit.NewResult()
var r2 audit.Result
require.NoError(t, r2.Unmarshal(data))
require.Equal(t, r, r2)
})
t.Run("json", func(t *testing.T) {
data, err := r.MarshalJSON()
require.NoError(t, err)
r2 := audit.NewResult()
require.NoError(t, r2.UnmarshalJSON(data))
require.Equal(t, r, r2)
})
}
func TestResult_ToV2(t *testing.T) {
t.Run("nil", func(t *testing.T) {
var x *audit.Result
require.Nil(t, x.ToV2())
})
t.Run("default values", func(t *testing.T) {
result := audit.NewResult()
// check initial values
require.Equal(t, version.Current(), result.Version())
require.False(t, result.Complete())
require.Nil(t, result.ContainerID())
require.Nil(t, result.PublicKey())
require.Nil(t, result.PassSG())
require.Nil(t, result.FailSG())
require.Nil(t, result.PassNodes())
require.Nil(t, result.FailNodes())
require.Zero(t, result.Hit())
require.Zero(t, result.Miss())
require.Zero(t, result.Fail())
require.Zero(t, result.Requests())
require.Zero(t, result.Retries())
require.Zero(t, result.AuditEpoch())
// convert to v2 message
resultV2 := result.ToV2()
require.Equal(t, version.Current().ToV2(), resultV2.GetVersion())
require.False(t, resultV2.GetComplete())
require.Nil(t, resultV2.GetContainerID())
require.Nil(t, resultV2.GetPublicKey())
require.Nil(t, resultV2.GetPassSG())
require.Nil(t, resultV2.GetFailSG())
require.Nil(t, resultV2.GetPassNodes())
require.Nil(t, resultV2.GetFailNodes())
require.Zero(t, resultV2.GetHit())
require.Zero(t, resultV2.GetMiss())
require.Zero(t, resultV2.GetFail())
require.Zero(t, resultV2.GetRequests())
require.Zero(t, resultV2.GetRetries())
require.Zero(t, resultV2.GetAuditEpoch())
})
}
func TestNewResultFromV2(t *testing.T) {
t.Run("from nil", func(t *testing.T) {
var x *auditv2.DataAuditResult
require.Nil(t, audit.NewResultFromV2(x))
})
}

13
audit/test/doc.go Normal file
View file

@ -0,0 +1,13 @@
/*
Package audittest provides functions for convenient testing of audit package API.
Note that importing the package into source files is highly discouraged.
Random instance generation functions can be useful when testing expects any value, e.g.:
import audittest "github.com/nspcc-dev/neofs-sdk-go/audit/test"
dec := audittest.Result()
// test the value
*/
package audittest

View file

@ -3,35 +3,34 @@ package audittest
import (
"github.com/nspcc-dev/neofs-sdk-go/audit"
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
oidtest "github.com/nspcc-dev/neofs-sdk-go/object/id/test"
versiontest "github.com/nspcc-dev/neofs-sdk-go/version/test"
)
// Result returns random audit.Result.
func Result() *audit.Result {
x := audit.NewResult()
var x audit.Result
x.SetVersion(versiontest.Version())
x.SetContainerID(cidtest.ID())
x.SetPublicKey([]byte("key"))
x.SetComplete(true)
x.SetAuditEpoch(44)
x.SetHit(55)
x.SetMiss(66)
x.SetFail(77)
x.SetRetries(88)
x.SetRequests(99)
x.SetFailNodes([][]byte{
x.ForContainer(*cidtest.ID())
x.SetAuditorKey([]byte("key"))
x.Complete()
x.ForEpoch(44)
x.SetHits(55)
x.SetMisses(66)
x.SetFailures(77)
x.SetRequestsPoR(88)
x.SetRequestsPoR(99)
x.SubmitFailedStorageNodes([][]byte{
[]byte("node1"),
[]byte("node2"),
})
x.SetPassNodes([][]byte{
x.SubmitPassedStorageNodes([][]byte{
[]byte("node3"),
[]byte("node4"),
})
x.SetPassSG([]oid.ID{*oidtest.ID(), *oidtest.ID()})
x.SetFailSG([]oid.ID{*oidtest.ID(), *oidtest.ID()})
x.SubmitPassedStorageGroup(*oidtest.ID())
x.SubmitPassedStorageGroup(*oidtest.ID())
x.SubmitFailedStorageGroup(*oidtest.ID())
x.SubmitFailedStorageGroup(*oidtest.ID())
return x
return &x
}