@@ -3,15 +3,52 @@ package object_test
33import (
44 "bytes"
55 "crypto/rand"
6+ "crypto/sha256"
67 "io"
8+ "math"
9+ "slices"
710 "testing"
811
912 iobject "github.com/nspcc-dev/neofs-node/internal/object"
13+ iprotobuf "github.com/nspcc-dev/neofs-node/internal/protobuf"
14+ "github.com/nspcc-dev/neofs-node/internal/testutil"
15+ "github.com/nspcc-dev/neofs-sdk-go/checksum"
16+ cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
17+ neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto"
18+ neofscryptotest "github.com/nspcc-dev/neofs-sdk-go/crypto/test"
1019 "github.com/nspcc-dev/neofs-sdk-go/object"
20+ oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
21+ oidtest "github.com/nspcc-dev/neofs-sdk-go/object/id/test"
1122 objecttest "github.com/nspcc-dev/neofs-sdk-go/object/test"
23+ "github.com/nspcc-dev/neofs-sdk-go/version"
24+ "github.com/nspcc-dev/tzhash/tz"
1225 "github.com/stretchr/testify/require"
26+ "google.golang.org/protobuf/encoding/protowire"
1327)
1428
29+ func TestFields (t * testing.T ) {
30+ require .EqualValues (t , 1 , iobject .FieldHeaderVersion )
31+ require .EqualValues (t , 2 , iobject .FieldHeaderContainerID )
32+ require .EqualValues (t , 3 , iobject .FieldHeaderOwnerID )
33+ require .EqualValues (t , 4 , iobject .FieldHeaderCreationEpoch )
34+ require .EqualValues (t , 5 , iobject .FieldHeaderPayloadLength )
35+ require .EqualValues (t , 6 , iobject .FieldHeaderPayloadHash )
36+ require .EqualValues (t , 7 , iobject .FieldHeaderType )
37+ require .EqualValues (t , 8 , iobject .FieldHeaderHomoHash )
38+ require .EqualValues (t , 9 , iobject .FieldHeaderSessionToken )
39+ require .EqualValues (t , 10 , iobject .FieldHeaderAttributes )
40+ require .EqualValues (t , 11 , iobject .FieldHeaderSplit )
41+ require .EqualValues (t , 12 , iobject .FieldHeaderSessionTokenV2 )
42+
43+ require .EqualValues (t , 1 , iobject .FieldHeaderSplitParent )
44+ require .EqualValues (t , 2 , iobject .FieldHeaderSplitPrevious )
45+ require .EqualValues (t , 3 , iobject .FieldHeaderSplitParentSignature )
46+ require .EqualValues (t , 4 , iobject .FieldHeaderSplitParentHeader )
47+ require .EqualValues (t , 5 , iobject .FieldHeaderSplitChildren )
48+ require .EqualValues (t , 6 , iobject .FieldHeaderSplitSplitID )
49+ require .EqualValues (t , 7 , iobject .FieldHeaderSplitFirst )
50+ }
51+
1552func TestWriteWithoutPayload (t * testing.T ) {
1653 t .Run ("write empty object" , func (t * testing.T ) {
1754 var buf bytes.Buffer
@@ -97,3 +134,158 @@ func TestReadHeaderPrefix(t *testing.T) {
97134 require .Equal (t , expectedSize , len (payloadPrefix ))
98135 require .Equal (t , payload [:expectedSize ], payloadPrefix )
99136}
137+
138+ func TestGetNonPayloadFieldBounds (t * testing.T ) {
139+ id := oidtest .ID ()
140+ sig := neofscryptotest .Signature ()
141+
142+ obj := objecttest .Object ()
143+ obj .SetID (id )
144+ obj .SetSignature (& sig )
145+
146+ buf := obj .Marshal ()
147+
148+ idf , sigf , hdrf , err := iobject .GetNonPayloadFieldBounds (buf )
149+ require .NoError (t , err )
150+
151+ assertFound := func (t * testing.T , f iprotobuf.FieldBounds , tag byte , exp []byte ) {
152+ require .False (t , f .IsMissing ())
153+ require .EqualValues (t , tag , buf [f .From ])
154+ ln , n , err := iprotobuf .ParseLENField (buf [f .From + 1 :], 42 , protowire .BytesType )
155+ require .NoError (t , err )
156+ require .EqualValues (t , 1 + n , f .ValueFrom - f .From )
157+ require .EqualValues (t , ln , f .To - f .ValueFrom )
158+ require .True (t , bytes .Equal (exp , buf [f .ValueFrom :f .To ]))
159+ }
160+
161+ assertFound (t , idf , iprotobuf .TagBytes1 , id .Marshal ())
162+ assertFound (t , sigf , iprotobuf .TagBytes2 , sig .Marshal ())
163+
164+ hdr := obj .ProtoMessage ().Header
165+ hdrBuf := make ([]byte , hdr .MarshaledSize ())
166+ hdr .MarshalStable (hdrBuf )
167+ assertFound (t , hdrf , iprotobuf .TagBytes3 , hdrBuf )
168+ }
169+
170+ func BenchmarkGetNonPayloadFieldBounds (b * testing.B ) {
171+ id := oidtest .ID ()
172+ const sigLen = 100
173+ const hdrLen = 16 << 10
174+
175+ buf := slices .Concat (
176+ []byte {iprotobuf .TagBytes1 , oid .Size + 2 , iprotobuf .TagBytes1 , oid .Size }, id [:],
177+ []byte {iprotobuf .TagBytes2 , sigLen }, testutil .RandByteSlice (sigLen ),
178+ []byte {iprotobuf .TagBytes3 , 128 , 128 , 1 }, testutil .RandByteSlice (hdrLen ),
179+ )
180+
181+ idf , sigf , hdrf , err := iobject .GetNonPayloadFieldBounds (buf )
182+ require .NoError (b , err )
183+ require .EqualValues (b , 0 , idf .From )
184+ require .EqualValues (b , idf .From + 2 , idf .ValueFrom )
185+ require .EqualValues (b , idf .ValueFrom + oid .Size , idf .To )
186+ require .EqualValues (b , idf .To , sigf .From )
187+ require .EqualValues (b , sigf .From + 2 , sigf .ValueFrom )
188+ require .EqualValues (b , sigf .ValueFrom + sigLen , sigf .To )
189+ require .EqualValues (b , sigf .To , hdrf .From )
190+ require .EqualValues (b , hdrf .From + 4 , hdrf .ValueFrom )
191+ require .EqualValues (b , hdrf .ValueFrom + hdrLen , hdrf .To )
192+ require .EqualValues (b , len (buf ), hdrf .To )
193+
194+ b .ReportAllocs ()
195+ for b .Loop () {
196+ _ , _ , _ , err = iobject .GetNonPayloadFieldBounds (buf )
197+ require .NoError (b , err )
198+ }
199+ }
200+
201+ func TestGetParentNonPayloadFieldBounds (t * testing.T ) {
202+ parID := oidtest .ID ()
203+ parSig := neofscryptotest .Signature ()
204+
205+ par := objecttest .Object ()
206+ par .SetID (parID )
207+ par .SetSignature (& parSig )
208+ par .ResetRelations ()
209+
210+ obj := objecttest .Object ()
211+ obj .SetParent (& par )
212+
213+ buf := obj .Marshal ()
214+
215+ idf , sigf , hdrf , err := iobject .GetParentNonPayloadFieldBounds (buf )
216+ require .NoError (t , err )
217+
218+ assertFound := func (t * testing.T , f iprotobuf.FieldBounds , tag byte , exp []byte ) {
219+ require .False (t , f .IsMissing ())
220+ require .EqualValues (t , tag , buf [f .From ])
221+ ln , n , err := iprotobuf .ParseLENField (buf [f .From + 1 :], 42 , protowire .BytesType )
222+ require .NoError (t , err )
223+ require .EqualValues (t , 1 + n , f .ValueFrom - f .From )
224+ require .EqualValues (t , ln , f .To - f .ValueFrom )
225+ require .True (t , bytes .Equal (exp , buf [f .ValueFrom :f .To ]))
226+ }
227+
228+ assertFound (t , idf , iprotobuf .TagBytes1 , parID .Marshal ())
229+ assertFound (t , sigf , iprotobuf .TagBytes3 , parSig .Marshal ())
230+
231+ parHdr := par .ProtoMessage ().Header
232+ parHdrBuf := make ([]byte , parHdr .MarshaledSize ())
233+ parHdr .MarshalStable (parHdrBuf )
234+ assertFound (t , hdrf , iprotobuf .TagBytes4 , parHdrBuf )
235+ }
236+
237+ func BenchmarkGetParentNonPayloadFieldBounds (b * testing.B ) {
238+ parID := oidtest .ID ()
239+
240+ sig := neofscrypto .NewSignatureFromRawKey (neofscrypto .ECDSA_DETERMINISTIC_SHA256 , testutil .RandByteSlice (33 ), testutil .RandByteSlice (64 ))
241+ ver := version .New (123 , 456 )
242+ pldHash := checksum .New (checksum .SHA256 , testutil .RandByteSlice (sha256 .Size ))
243+ pldHomoHash := checksum .New (checksum .TillichZemor , testutil .RandByteSlice (tz .Size ))
244+
245+ fillHeader := func (obj * object.Object ) {
246+ obj .SetID (oidtest .ID ())
247+ obj .SetSignature (& sig )
248+ obj .SetVersion (& ver )
249+ obj .SetContainerID (cidtest .ID ())
250+ obj .SetCreationEpoch (math .MaxUint64 )
251+ obj .SetPayloadSize (math .MaxUint64 )
252+ obj .SetPayloadChecksum (pldHash )
253+ obj .SetType (math .MaxInt32 )
254+ obj .SetPayloadHomomorphicHash (pldHomoHash )
255+ obj .SetAttributes (
256+ object .NewAttribute ("key1" , "val1" ),
257+ object .NewAttribute ("key2" , "val2" ),
258+ object .NewAttribute ("key3" , "val3" ),
259+ )
260+ }
261+
262+ var par object.Object
263+ fillHeader (& par )
264+ par .SetID (parID )
265+
266+ var obj object.Object
267+ fillHeader (& obj )
268+ obj .SetPreviousID (oidtest .ID ())
269+ obj .SetParent (& par )
270+
271+ buf := obj .Marshal ()
272+
273+ idf , sigf , hdrf , err := iobject .GetParentNonPayloadFieldBounds (buf )
274+ require .NoError (b , err )
275+ require .Positive (b , idf .From )
276+ require .EqualValues (b , idf .From + 2 , idf .ValueFrom )
277+ require .EqualValues (b , idf .ValueFrom + 2 + oid .Size , idf .To )
278+ require .EqualValues (b , idf .To + 2 + 2 + oid .Size , sigf .From )
279+ require .EqualValues (b , sigf .From + 2 , sigf .ValueFrom )
280+ require .EqualValues (b , sigf .ValueFrom + len (sig .Marshal ()), sigf .To )
281+ require .EqualValues (b , sigf .To , hdrf .From )
282+ require .EqualValues (b , hdrf .From + 3 , hdrf .ValueFrom )
283+ require .EqualValues (b , hdrf .ValueFrom + par .HeaderLen (), hdrf .To )
284+ require .EqualValues (b , len (buf ), hdrf .To )
285+
286+ b .ReportAllocs ()
287+ for b .Loop () {
288+ _ , _ , _ , err = iobject .GetNonPayloadFieldBounds (buf )
289+ require .NoError (b , err )
290+ }
291+ }
0 commit comments