forked from TrueCloudLab/frostfs-sdk-go
[#210] subnet: Refactor and document package functionality
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
6709b00c89
commit
eb3b990812
13 changed files with 276 additions and 216 deletions
|
@ -36,13 +36,31 @@ func (p *PlacementPolicy) ToV2() *netmap.PlacementPolicy {
|
|||
|
||||
// SubnetID returns subnet to select nodes from.
|
||||
func (p *PlacementPolicy) SubnetID() *subnetid.ID {
|
||||
return (*subnetid.ID)(
|
||||
(*netmap.PlacementPolicy)(p).GetSubnetID())
|
||||
idv2 := (*netmap.PlacementPolicy)(p).GetSubnetID()
|
||||
if idv2 == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var id subnetid.ID
|
||||
|
||||
err := id.ReadFromV2(*idv2)
|
||||
if err != nil {
|
||||
panic(err) // will disappear after netmap package refactor
|
||||
}
|
||||
|
||||
return &id
|
||||
}
|
||||
|
||||
// SetSubnetID sets subnet to select nodes from.
|
||||
func (p *PlacementPolicy) SetSubnetID(subnet *subnetid.ID) {
|
||||
(*netmap.PlacementPolicy)(p).SetSubnetID((*refs.SubnetID)(subnet))
|
||||
var idv2 *refs.SubnetID
|
||||
|
||||
if subnet != nil {
|
||||
idv2 = new(refs.SubnetID)
|
||||
subnet.WriteToV2(idv2)
|
||||
}
|
||||
|
||||
(*netmap.PlacementPolicy)(p).SetSubnetID(idv2)
|
||||
}
|
||||
|
||||
// Replicas returns list of object replica descriptors.
|
||||
|
|
|
@ -2,6 +2,7 @@ package netmap
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/netmap"
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||
|
@ -48,9 +49,12 @@ func (i *NodeInfo) IterateSubnets(f func(subnetid.ID) error) error {
|
|||
var id subnetid.ID
|
||||
|
||||
return netmap.IterateSubnets((*netmap.NodeInfo)(i), func(idv2 refs.SubnetID) error {
|
||||
id.FromV2(idv2)
|
||||
err := id.ReadFromV2(idv2)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid subnet: %w", err)
|
||||
}
|
||||
|
||||
err := f(id)
|
||||
err = f(id)
|
||||
if errors.Is(err, ErrRemoveSubnet) {
|
||||
return netmap.ErrRemoveSubnet
|
||||
}
|
||||
|
@ -66,7 +70,7 @@ var errAbortSubnetIter = errors.New("abort subnet iterator")
|
|||
// Function is NPE-safe: nil NodeInfo always belongs to zero subnet only.
|
||||
func BelongsToSubnet(node *NodeInfo, id subnetid.ID) bool {
|
||||
err := node.IterateSubnets(func(id_ subnetid.ID) error {
|
||||
if id.Equals(&id_) {
|
||||
if id.Equals(id_) {
|
||||
return errAbortSubnetIter
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ func TestNodeInfoSubnets(t *testing.T) {
|
|||
t.Run("enter subnet", func(t *testing.T) {
|
||||
var id subnetid.ID
|
||||
|
||||
id.SetNumber(13)
|
||||
id.SetNumeric(13)
|
||||
|
||||
var node netmap.NodeInfo
|
||||
|
||||
|
@ -35,8 +35,8 @@ func TestNodeInfoSubnets(t *testing.T) {
|
|||
t.Run("not last", func(t *testing.T) {
|
||||
var id, idrm subnetid.ID
|
||||
|
||||
id.SetNumber(13)
|
||||
idrm.SetNumber(23)
|
||||
id.SetNumeric(13)
|
||||
idrm.SetNumeric(23)
|
||||
|
||||
var node netmap.NodeInfo
|
||||
|
||||
|
@ -44,7 +44,7 @@ func TestNodeInfoSubnets(t *testing.T) {
|
|||
node.EnterSubnet(idrm)
|
||||
|
||||
err := node.IterateSubnets(func(id subnetid.ID) error {
|
||||
if subnetid.IsZero(id) || id.Equals(&idrm) {
|
||||
if subnetid.IsZero(id) || id.Equals(idrm) {
|
||||
return netmap.ErrRemoveSubnet
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,7 @@ func TestEnterSubnet(t *testing.T) {
|
|||
node.ExitSubnet(id)
|
||||
require.False(t, netmap.BelongsToSubnet(&node, id))
|
||||
|
||||
id.SetNumber(10)
|
||||
id.SetNumeric(10)
|
||||
node.EnterSubnet(id)
|
||||
require.True(t, netmap.BelongsToSubnet(&node, id))
|
||||
require.False(t, netmap.BelongsToSubnet(&node, subnetid.ID{}))
|
||||
|
@ -113,8 +113,8 @@ func TestEnterSubnet(t *testing.T) {
|
|||
func TestBelongsToSubnet(t *testing.T) {
|
||||
var id, idMiss, idZero subnetid.ID
|
||||
|
||||
id.SetNumber(13)
|
||||
idMiss.SetNumber(23)
|
||||
id.SetNumeric(13)
|
||||
idMiss.SetNumeric(23)
|
||||
|
||||
var node netmap.NodeInfo
|
||||
|
||||
|
|
10
subnet/doc.go
Normal file
10
subnet/doc.go
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
Package subnet collects functionality related to the NeoFS subnets.
|
||||
|
||||
Subnet of a particular NeoFS network consists of a subset of the storage nodes
|
||||
of that network. Subnet of the whole network is called zero. Info type acts as
|
||||
a subnet descriptor. Each subnet is owned by the user who created it. Information
|
||||
about all subnets is stored in the Subnet contract of the NeoFS Sidechain.
|
||||
|
||||
*/
|
||||
package subnet
|
10
subnet/id/doc.go
Normal file
10
subnet/id/doc.go
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
Package subnetid provides primitives to work with subnet identification in NeoFS.
|
||||
|
||||
ID type is used for global subnet identity inside the NeoFS network.
|
||||
|
||||
Using package types in an application is recommended to potentially work with
|
||||
different protocol versions with which these types are compatible.
|
||||
|
||||
*/
|
||||
package subnetid
|
121
subnet/id/id.go
121
subnet/id/id.go
|
@ -2,95 +2,104 @@ package subnetid
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||
)
|
||||
|
||||
// ID represents NeoFS subnet identifier.
|
||||
// ID represents unique identifier of the subnet in the NeoFS network.
|
||||
//
|
||||
// The type is compatible with the corresponding message from NeoFS API V2 protocol.
|
||||
// ID is mutually compatible with github.com/nspcc-dev/neofs-api-go/v2/refs.SubnetID
|
||||
// message. See ReadFromV2 / WriteToV2 methods.
|
||||
//
|
||||
// Zero value and nil pointer is equivalent to zero subnet ID.
|
||||
type ID refs.SubnetID
|
||||
|
||||
// FromV2 initializes ID from refs.SubnetID message structure. Must not be called on nil.
|
||||
//
|
||||
// Note: nil refs.SubnetID corresponds to zero ID value or nil pointer to it.
|
||||
func (x *ID) FromV2(msg refs.SubnetID) {
|
||||
*x = ID(msg)
|
||||
// Instances can be created using built-in var declaration. Zero value is
|
||||
// equivalent to identifier of the zero subnet (whole NeoFS network).
|
||||
type ID struct {
|
||||
m refs.SubnetID
|
||||
}
|
||||
|
||||
// WriteToV2 writes ID to refs.SubnetID message structure. The message must not be nil.
|
||||
// ReadFromV2 reads ID from the refs.SubnetID message. Checks if the
|
||||
// message conforms to NeoFS API V2 protocol.
|
||||
//
|
||||
// Note: nil ID corresponds to zero refs.SubnetID value or nil pointer to it.
|
||||
// See also WriteToV2.
|
||||
func (x *ID) ReadFromV2(msg refs.SubnetID) error {
|
||||
x.m = msg
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteToV2 writes ID to refs.SubnetID message structure. The message MUST NOT
|
||||
// be nil.
|
||||
//
|
||||
// See also ReadFromV2.
|
||||
func (x ID) WriteToV2(msg *refs.SubnetID) {
|
||||
*msg = refs.SubnetID(x)
|
||||
*msg = x.m
|
||||
}
|
||||
|
||||
// Equals returns true iff both instances identify the same subnet.
|
||||
// Equals defines a comparison relation between two ID instances.
|
||||
//
|
||||
// Method is NPE-safe: nil pointer equals to pointer to zero value.
|
||||
func (x *ID) Equals(x2 *ID) bool {
|
||||
return (*refs.SubnetID)(x).GetValue() == (*refs.SubnetID)(x2).GetValue()
|
||||
// Note that comparison using '==' operator is not recommended since it MAY result
|
||||
// in loss of compatibility.
|
||||
func (x ID) Equals(x2 ID) bool {
|
||||
return x.m.GetValue() == x2.m.GetValue()
|
||||
}
|
||||
|
||||
// MarshalText encodes ID into text format according to particular NeoFS API protocol.
|
||||
// Supported versions:
|
||||
// * V2 (see refs.SubnetID type).
|
||||
// EncodeToString encodes ID into NeoFS API protocol string (base10 encoding).
|
||||
//
|
||||
// Implements encoding.TextMarshaler.
|
||||
func (x *ID) MarshalText() ([]byte, error) {
|
||||
return (*refs.SubnetID)(x).MarshalText()
|
||||
// See also DecodeString.
|
||||
func (x ID) EncodeToString() string {
|
||||
return strconv.FormatUint(uint64(x.m.GetValue()), 10)
|
||||
}
|
||||
|
||||
// UnmarshalText decodes ID from the text according to particular NeoFS API protocol.
|
||||
// Must not be called on nil. Supported versions:
|
||||
// * V2 (see refs.SubnetID type).
|
||||
//
|
||||
// Implements encoding.TextUnmarshaler.
|
||||
func (x *ID) UnmarshalText(text []byte) error {
|
||||
return (*refs.SubnetID)(x).UnmarshalText(text)
|
||||
}
|
||||
|
||||
// String returns string representation of ID using MarshalText.
|
||||
// Returns string with message on error.
|
||||
//
|
||||
// Implements fmt.Stringer.
|
||||
func (x *ID) String() string {
|
||||
text, err := x.MarshalText()
|
||||
// DecodeString decodes string calculated using EncodeToString. Returns
|
||||
// an error if s is malformed.
|
||||
func (x *ID) DecodeString(s string) error {
|
||||
num, err := strconv.ParseUint(s, 10, 32)
|
||||
if err != nil {
|
||||
return fmt.Sprintf("<invalid> %v", err)
|
||||
return fmt.Errorf("invalid numeric value: %w", err)
|
||||
}
|
||||
|
||||
return string(text)
|
||||
x.m.SetValue(uint32(num))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Marshal encodes ID into a binary format of NeoFS API V2 protocol (Protocol Buffers with direct field order).
|
||||
func (x *ID) Marshal() ([]byte, error) {
|
||||
return (*refs.SubnetID)(x).StableMarshal(nil), nil
|
||||
}
|
||||
|
||||
// Unmarshal decodes ID from NeoFS API V2 binary format (see Marshal). Must not be called on nil.
|
||||
// String implements fmt.Stringer.
|
||||
//
|
||||
// Note: empty data corresponds to zero ID value or nil pointer to it.
|
||||
// String is designed to be human-readable, and its format MAY differ between
|
||||
// SDK versions. String MAY return same result as EncodeToString. String MUST NOT
|
||||
// be used to encode ID into NeoFS protocol string.
|
||||
func (x ID) String() string {
|
||||
return "#" + strconv.FormatUint(uint64(x.m.GetValue()), 10)
|
||||
}
|
||||
|
||||
// Marshal encodes ID into a binary format of the NeoFS API protocol
|
||||
// (Protocol Buffers with direct field order).
|
||||
//
|
||||
// See also Unmarshal.
|
||||
func (x ID) Marshal() []byte {
|
||||
return x.m.StableMarshal(nil)
|
||||
}
|
||||
|
||||
// Unmarshal decodes binary ID calculated using Marshal. Returns an error
|
||||
// describing a format violation.
|
||||
func (x *ID) Unmarshal(data []byte) error {
|
||||
return (*refs.SubnetID)(x).Unmarshal(data)
|
||||
return x.m.Unmarshal(data)
|
||||
}
|
||||
|
||||
// SetNumber sets ID value in uint32 format. Must not be called on nil.
|
||||
// By default, number is 0 which refers to zero subnet.
|
||||
func (x *ID) SetNumber(num uint32) {
|
||||
(*refs.SubnetID)(x).SetValue(num)
|
||||
// SetNumeric sets ID value in numeric format. By default, number is 0 which
|
||||
// refers to the zero subnet.
|
||||
func (x *ID) SetNumeric(num uint32) {
|
||||
x.m.SetValue(num)
|
||||
}
|
||||
|
||||
// IsZero returns true iff the ID refers to zero subnet.
|
||||
// IsZero compares id with zero subnet ID.
|
||||
func IsZero(id ID) bool {
|
||||
return id.Equals(nil)
|
||||
return id.Equals(ID{})
|
||||
}
|
||||
|
||||
// MakeZero makes ID to refer to zero subnet. Arg must not be nil (it is already zero).
|
||||
// MakeZero makes ID to refer to zero subnet.
|
||||
//
|
||||
// Makes no sense to call on zero value (e.g. declared using var).
|
||||
func MakeZero(id *ID) {
|
||||
id.SetNumber(0)
|
||||
id.SetNumeric(0)
|
||||
}
|
||||
|
|
|
@ -14,26 +14,26 @@ func TestIsZero(t *testing.T) {
|
|||
|
||||
require.True(t, subnetid.IsZero(id))
|
||||
|
||||
id.SetNumber(13)
|
||||
id.SetNumeric(13)
|
||||
require.False(t, subnetid.IsZero(id))
|
||||
|
||||
id.SetNumber(0)
|
||||
id.SetNumeric(0)
|
||||
require.True(t, subnetid.IsZero(id))
|
||||
}
|
||||
|
||||
func TestID_FromV2(t *testing.T) {
|
||||
func TestID_ReadFromV2(t *testing.T) {
|
||||
const num = 13
|
||||
|
||||
var id1 subnetid.ID
|
||||
id1.SetNumber(num)
|
||||
id1.SetNumeric(num)
|
||||
|
||||
var idv2 refs.SubnetID
|
||||
idv2.SetValue(num)
|
||||
|
||||
var id2 subnetid.ID
|
||||
id2.FromV2(idv2)
|
||||
require.NoError(t, id2.ReadFromV2(idv2))
|
||||
|
||||
require.True(t, id1.Equals(&id2))
|
||||
require.True(t, id1.Equals(id2))
|
||||
}
|
||||
|
||||
func TestID_WriteToV2(t *testing.T) {
|
||||
|
@ -47,7 +47,7 @@ func TestID_WriteToV2(t *testing.T) {
|
|||
id.WriteToV2(&idv2)
|
||||
require.Zero(t, idv2.GetValue())
|
||||
|
||||
id.SetNumber(num)
|
||||
id.SetNumeric(num)
|
||||
|
||||
id.WriteToV2(&idv2)
|
||||
require.EqualValues(t, num, idv2.GetValue())
|
||||
|
@ -58,36 +58,30 @@ func TestID_Equals(t *testing.T) {
|
|||
|
||||
var id1, id2, idOther, id0 subnetid.ID
|
||||
|
||||
id0.Equals(nil)
|
||||
id0.Equals(subnetid.ID{})
|
||||
|
||||
id1.SetNumber(num)
|
||||
id2.SetNumber(num)
|
||||
idOther.SetNumber(num + 1)
|
||||
id1.SetNumeric(num)
|
||||
id2.SetNumeric(num)
|
||||
idOther.SetNumeric(num + 1)
|
||||
|
||||
require.True(t, id1.Equals(&id2))
|
||||
require.False(t, id1.Equals(&idOther))
|
||||
require.False(t, id2.Equals(&idOther))
|
||||
require.True(t, id1.Equals(id2))
|
||||
require.False(t, id1.Equals(idOther))
|
||||
require.False(t, id2.Equals(idOther))
|
||||
}
|
||||
|
||||
func TestSubnetIDEncoding(t *testing.T) {
|
||||
id := subnetidtest.ID()
|
||||
|
||||
t.Run("binary", func(t *testing.T) {
|
||||
data, err := id.Marshal()
|
||||
require.NoError(t, err)
|
||||
|
||||
var id2 subnetid.ID
|
||||
require.NoError(t, id2.Unmarshal(data))
|
||||
require.NoError(t, id2.Unmarshal(id.Marshal()))
|
||||
|
||||
require.True(t, id2.Equals(id))
|
||||
})
|
||||
|
||||
t.Run("text", func(t *testing.T) {
|
||||
data, err := id.MarshalText()
|
||||
require.NoError(t, err)
|
||||
|
||||
var id2 subnetid.ID
|
||||
require.NoError(t, id2.UnmarshalText(data))
|
||||
require.NoError(t, id2.DecodeString(id.EncodeToString()))
|
||||
|
||||
require.True(t, id2.Equals(id))
|
||||
})
|
||||
|
@ -95,12 +89,12 @@ func TestSubnetIDEncoding(t *testing.T) {
|
|||
|
||||
func TestMakeZero(t *testing.T) {
|
||||
var id subnetid.ID
|
||||
|
||||
id.SetNumber(13)
|
||||
id.SetNumeric(13)
|
||||
|
||||
require.False(t, subnetid.IsZero(id))
|
||||
|
||||
subnetid.MakeZero(&id)
|
||||
|
||||
require.True(t, subnetid.IsZero(id))
|
||||
require.Equal(t, subnetid.ID{}, id)
|
||||
}
|
||||
|
|
13
subnet/id/test/doc.go
Normal file
13
subnet/id/test/doc.go
Normal file
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
Package subnetidtest provides functions for convenient testing of subnetid 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 subnetidtest "github.com/nspcc-dev/neofs-sdk-go/suibnet/id/test"
|
||||
|
||||
value := subnetidtest.ID()
|
||||
// test the value
|
||||
|
||||
*/
|
||||
package subnetidtest
|
|
@ -6,11 +6,8 @@ import (
|
|||
subnetid "github.com/nspcc-dev/neofs-sdk-go/subnet/id"
|
||||
)
|
||||
|
||||
// ID generates and returns random subnetid.ID using math/rand.Uint32.
|
||||
func ID() *subnetid.ID {
|
||||
var id subnetid.ID
|
||||
|
||||
id.SetNumber(rand.Uint32())
|
||||
|
||||
return &id
|
||||
// ID generates and returns random subnetid.ID.
|
||||
func ID() (x subnetid.ID) {
|
||||
x.SetNumeric(rand.Uint32())
|
||||
return
|
||||
}
|
||||
|
|
155
subnet/subnet.go
155
subnet/subnet.go
|
@ -1,6 +1,8 @@
|
|||
package subnet
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/subnet"
|
||||
subnetid "github.com/nspcc-dev/neofs-sdk-go/subnet/id"
|
||||
|
@ -9,102 +11,99 @@ import (
|
|||
|
||||
// Info represents information about NeoFS subnet.
|
||||
//
|
||||
// The type is compatible with the corresponding message from NeoFS API V2 protocol.
|
||||
// Instances can be created using built-in var declaration.
|
||||
type Info struct {
|
||||
id subnetid.ID
|
||||
|
||||
owner user.ID
|
||||
}
|
||||
|
||||
// Marshal encodes Info into a binary format of the NeoFS API protocol
|
||||
// (Protocol Buffers with direct field order).
|
||||
//
|
||||
// Zero value and nil pointer to it represents zero subnet w/o an owner.
|
||||
type Info subnet.Info
|
||||
// See also Unmarshal.
|
||||
func (x Info) Marshal() []byte {
|
||||
var id refs.SubnetID
|
||||
x.id.WriteToV2(&id)
|
||||
|
||||
// FromV2 initializes Info from subnet.Info message structure. Must not be called on nil.
|
||||
func (x *Info) FromV2(msg subnet.Info) {
|
||||
*x = Info(msg)
|
||||
var owner refs.OwnerID
|
||||
x.owner.WriteToV2(&owner)
|
||||
|
||||
var m subnet.Info
|
||||
m.SetID(&id)
|
||||
m.SetOwner(&owner)
|
||||
|
||||
return m.StableMarshal(nil)
|
||||
}
|
||||
|
||||
// WriteToV2 writes Info to subnet.Info message structure. The message must not be nil.
|
||||
func (x Info) WriteToV2(msg *subnet.Info) {
|
||||
*msg = subnet.Info(x)
|
||||
}
|
||||
|
||||
// Marshal encodes Info into a binary format of NeoFS API V2 protocol (Protocol Buffers with direct field order).
|
||||
func (x *Info) Marshal() ([]byte, error) {
|
||||
return (*subnet.Info)(x).StableMarshal(nil), nil
|
||||
}
|
||||
|
||||
// Unmarshal decodes Info from NeoFS API V2 binary format (see Marshal). Must not be called on nil.
|
||||
//
|
||||
// Note: empty data corresponds to zero Info value or nil pointer to it.
|
||||
// Unmarshal decodes binary Info calculated using Marshal. Returns an error
|
||||
// describing a format violation.
|
||||
func (x *Info) Unmarshal(data []byte) error {
|
||||
return (*subnet.Info)(x).Unmarshal(data)
|
||||
var m subnet.Info
|
||||
|
||||
err := m.Unmarshal(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
id := m.ID()
|
||||
if id != nil {
|
||||
err = x.id.ReadFromV2(*id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid ID: %w", err)
|
||||
}
|
||||
} else {
|
||||
subnetid.MakeZero(&x.id)
|
||||
}
|
||||
|
||||
owner := m.Owner()
|
||||
if owner != nil {
|
||||
err = x.owner.ReadFromV2(*owner)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid owner: %w", err)
|
||||
}
|
||||
} else {
|
||||
x.owner = user.ID{}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetID sets the identifier of the subnet that Info describes.
|
||||
//
|
||||
// See also ID.
|
||||
func (x *Info) SetID(id subnetid.ID) {
|
||||
infov2 := (*subnet.Info)(x)
|
||||
|
||||
idv2 := infov2.ID()
|
||||
if idv2 == nil {
|
||||
idv2 = new(refs.SubnetID)
|
||||
infov2.SetID(idv2)
|
||||
x.id = id
|
||||
}
|
||||
|
||||
id.WriteToV2(idv2)
|
||||
// ID returns subnet identifier set using SetID.
|
||||
//
|
||||
// Zero Info refers to the zero subnet.
|
||||
func (x Info) ID() subnetid.ID {
|
||||
return x.id
|
||||
}
|
||||
|
||||
// ReadID reads the identifier of the subnet that Info describes. Arg must not be nil.
|
||||
func (x Info) ReadID(id *subnetid.ID) {
|
||||
infov2 := (subnet.Info)(x)
|
||||
|
||||
idv2 := infov2.ID()
|
||||
if idv2 == nil {
|
||||
subnetid.MakeZero(id)
|
||||
return
|
||||
}
|
||||
|
||||
id.FromV2(*idv2)
|
||||
}
|
||||
|
||||
// SetOwner sets subnet owner ID.
|
||||
// SetOwner sets identifier of the subnet owner.
|
||||
func (x *Info) SetOwner(id user.ID) {
|
||||
infov2 := (*subnet.Info)(x)
|
||||
|
||||
idv2 := infov2.Owner()
|
||||
if idv2 == nil {
|
||||
idv2 = new(refs.OwnerID)
|
||||
infov2.SetOwner(idv2)
|
||||
x.owner = id
|
||||
}
|
||||
|
||||
id.WriteToV2(idv2)
|
||||
// Owner returns subnet owner set using SetOwner.
|
||||
//
|
||||
// Zero Info has no owner which is incorrect according to the
|
||||
// NeoFS API protocol.
|
||||
func (x Info) Owner() user.ID {
|
||||
return x.owner
|
||||
}
|
||||
|
||||
// ReadOwner reads the identifier of the subnet that Info describes.
|
||||
// Must be called only if owner is set (see HasOwner). Arg must not be nil.
|
||||
func (x Info) ReadOwner(id *user.ID) {
|
||||
infov2 := (subnet.Info)(x)
|
||||
|
||||
id2 := infov2.Owner()
|
||||
if id2 == nil {
|
||||
*id = user.ID{}
|
||||
return
|
||||
// AssertOwnership checks if the given info describes the subnet owned by the
|
||||
// given user.
|
||||
func AssertOwnership(info Info, id user.ID) bool {
|
||||
return id.Equals(info.Owner())
|
||||
}
|
||||
|
||||
if ownerV2 := infov2.Owner(); ownerV2 != nil {
|
||||
_ = id.ReadFromV2(*ownerV2)
|
||||
}
|
||||
}
|
||||
|
||||
// IsOwner checks subnet ownership.
|
||||
func IsOwner(info Info, id user.ID) bool {
|
||||
var id2 user.ID
|
||||
|
||||
info.ReadOwner(&id2)
|
||||
|
||||
return id.Equals(id2)
|
||||
}
|
||||
|
||||
// IDEquals checks if ID refers to subnet that Info describes.
|
||||
func IDEquals(info Info, id subnetid.ID) bool {
|
||||
id2 := new(subnetid.ID)
|
||||
|
||||
info.ReadID(id2)
|
||||
|
||||
return id.Equals(id2)
|
||||
// AssertReference checks if the given info describes the subnet referenced by
|
||||
// the given id.
|
||||
func AssertReference(info Info, id subnetid.ID) bool {
|
||||
return id.Equals(info.ID())
|
||||
}
|
||||
|
|
|
@ -3,11 +3,10 @@ package subnet_test
|
|||
import (
|
||||
"testing"
|
||||
|
||||
subnetv2 "github.com/nspcc-dev/neofs-api-go/v2/subnet"
|
||||
subnettest "github.com/nspcc-dev/neofs-api-go/v2/subnet/test"
|
||||
. "github.com/nspcc-dev/neofs-sdk-go/subnet"
|
||||
subnetid "github.com/nspcc-dev/neofs-sdk-go/subnet/id"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/user"
|
||||
subnetidtest "github.com/nspcc-dev/neofs-sdk-go/subnet/id/test"
|
||||
subnettest "github.com/nspcc-dev/neofs-sdk-go/subnet/test"
|
||||
usertest "github.com/nspcc-dev/neofs-sdk-go/user/test"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -15,55 +14,35 @@ import (
|
|||
func TestInfoZero(t *testing.T) {
|
||||
var info Info
|
||||
|
||||
var id subnetid.ID
|
||||
info.ReadID(&id)
|
||||
|
||||
require.True(t, subnetid.IsZero(id))
|
||||
require.Zero(t, info.ID())
|
||||
require.True(t, subnetid.IsZero(info.ID()))
|
||||
}
|
||||
|
||||
func TestInfo_SetID(t *testing.T) {
|
||||
var (
|
||||
id subnetid.ID
|
||||
info Info
|
||||
)
|
||||
|
||||
id.SetNumber(222)
|
||||
id := subnetidtest.ID()
|
||||
|
||||
var info Info
|
||||
info.SetID(id)
|
||||
|
||||
require.True(t, IDEquals(info, id))
|
||||
require.Equal(t, id, info.ID())
|
||||
require.True(t, AssertReference(info, id))
|
||||
}
|
||||
|
||||
func TestInfo_SetOwner(t *testing.T) {
|
||||
var (
|
||||
id user.ID
|
||||
info Info
|
||||
)
|
||||
|
||||
id = *usertest.ID()
|
||||
|
||||
require.False(t, IsOwner(info, id))
|
||||
id := *usertest.ID()
|
||||
|
||||
var info Info
|
||||
info.SetOwner(id)
|
||||
|
||||
require.True(t, IsOwner(info, id))
|
||||
require.Equal(t, id, info.Owner())
|
||||
require.True(t, AssertOwnership(info, id))
|
||||
}
|
||||
|
||||
func TestInfo_WriteToV2(t *testing.T) {
|
||||
var (
|
||||
infoTo, infoFrom Info
|
||||
func TestInfo_Marshal(t *testing.T) {
|
||||
info := subnettest.Info()
|
||||
|
||||
infoV2From, infoV2To subnetv2.Info
|
||||
)
|
||||
var info2 Info
|
||||
require.NoError(t, info2.Unmarshal(info.Marshal()))
|
||||
|
||||
infoV2From = *subnettest.GenerateSubnetInfo(false)
|
||||
|
||||
infoFrom.FromV2(infoV2From)
|
||||
|
||||
infoFrom.WriteToV2(&infoV2To)
|
||||
|
||||
infoTo.FromV2(infoV2To)
|
||||
|
||||
require.Equal(t, infoV2From, infoV2To)
|
||||
require.Equal(t, infoFrom, infoTo)
|
||||
require.Equal(t, info, info2)
|
||||
}
|
||||
|
|
13
subnet/test/doc.go
Normal file
13
subnet/test/doc.go
Normal file
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
Package subnettest provides functions for convenient testing of subnet 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 subnettest "github.com/nspcc-dev/neofs-sdk-go/suibnet/test"
|
||||
|
||||
value := subnettest.Info()
|
||||
// test the value
|
||||
|
||||
*/
|
||||
package subnettest
|
14
subnet/test/subnet.go
Normal file
14
subnet/test/subnet.go
Normal file
|
@ -0,0 +1,14 @@
|
|||
package subnettest
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neofs-sdk-go/subnet"
|
||||
subnetidtest "github.com/nspcc-dev/neofs-sdk-go/subnet/id/test"
|
||||
usertest "github.com/nspcc-dev/neofs-sdk-go/user/test"
|
||||
)
|
||||
|
||||
// Info generates and returns random subnet.Info.
|
||||
func Info() (x subnet.Info) {
|
||||
x.SetID(subnetidtest.ID())
|
||||
x.SetOwner(*usertest.ID())
|
||||
return
|
||||
}
|
Loading…
Reference in a new issue