forked from TrueCloudLab/frostfs-sdk-go
[#268] client: Make PayloadPatch
correctly receive empty patch payload
* Make the method `PatchPayload` send a patch with empty payload patch if range's length is non-zero and if it's the first call. * Empty payload patches just cut original object payload. So, these patches are also valid. Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
This commit is contained in:
parent
f0c599d06d
commit
d342c0bc16
2 changed files with 102 additions and 0 deletions
|
@ -175,6 +175,21 @@ func (x *objectPatcher) PatchPayload(_ context.Context, rng *object.Range, paylo
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
|
if patchIter == 0 {
|
||||||
|
if rng.GetLength() == 0 {
|
||||||
|
x.err = errors.New("zero-length empty payload patch can't be applied")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !x.patch(&object.Patch{
|
||||||
|
Address: x.addr,
|
||||||
|
PayloadPatch: &object.PayloadPatch{
|
||||||
|
Range: rng,
|
||||||
|
Chunk: []byte{},
|
||||||
|
},
|
||||||
|
}) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -193,6 +193,93 @@ func TestObjectPatcher(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRepeatPayloadPatch(t *testing.T) {
|
||||||
|
t.Run("no payload patch partioning", func(t *testing.T) {
|
||||||
|
m := &mockPatchStream{}
|
||||||
|
|
||||||
|
pk, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||||
|
|
||||||
|
const maxChunkLen = 20
|
||||||
|
|
||||||
|
patcher := objectPatcher{
|
||||||
|
client: &Client{},
|
||||||
|
stream: m,
|
||||||
|
addr: oidtest.Address(),
|
||||||
|
key: pk,
|
||||||
|
maxChunkLen: maxChunkLen,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pp := range []struct {
|
||||||
|
patchPayload string
|
||||||
|
rng *object.Range
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
patchPayload: "xxxxxxxxxx",
|
||||||
|
rng: newRange(1, 6),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
patchPayload: "yyyyyyyyyy",
|
||||||
|
rng: newRange(5, 9),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
patchPayload: "zzzzzzzzzz",
|
||||||
|
rng: newRange(10, 0),
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
success := patcher.PatchPayload(context.Background(), pp.rng, bytes.NewReader([]byte(pp.patchPayload)))
|
||||||
|
require.True(t, success)
|
||||||
|
}
|
||||||
|
|
||||||
|
requireRangeChunk(t, m.streamedPayloadPatches[0], 1, 6, "xxxxxxxxxx")
|
||||||
|
requireRangeChunk(t, m.streamedPayloadPatches[1], 5, 9, "yyyyyyyyyy")
|
||||||
|
requireRangeChunk(t, m.streamedPayloadPatches[2], 10, 0, "zzzzzzzzzz")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("payload patch partioning", func(t *testing.T) {
|
||||||
|
m := &mockPatchStream{}
|
||||||
|
|
||||||
|
pk, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||||
|
|
||||||
|
const maxChunkLen = 5
|
||||||
|
|
||||||
|
patcher := objectPatcher{
|
||||||
|
client: &Client{},
|
||||||
|
stream: m,
|
||||||
|
addr: oidtest.Address(),
|
||||||
|
key: pk,
|
||||||
|
maxChunkLen: maxChunkLen,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pp := range []struct {
|
||||||
|
patchPayload string
|
||||||
|
rng *object.Range
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
patchPayload: "xxxxxxxxxx",
|
||||||
|
rng: newRange(1, 6),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
patchPayload: "yyyyyyyyyy",
|
||||||
|
rng: newRange(5, 9),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
patchPayload: "zzzzzzzzzz",
|
||||||
|
rng: newRange(10, 0),
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
success := patcher.PatchPayload(context.Background(), pp.rng, bytes.NewReader([]byte(pp.patchPayload)))
|
||||||
|
require.True(t, success)
|
||||||
|
}
|
||||||
|
|
||||||
|
requireRangeChunk(t, m.streamedPayloadPatches[0], 1, 6, "xxxxx")
|
||||||
|
requireRangeChunk(t, m.streamedPayloadPatches[1], 7, 0, "xxxxx")
|
||||||
|
requireRangeChunk(t, m.streamedPayloadPatches[2], 5, 9, "yyyyy")
|
||||||
|
requireRangeChunk(t, m.streamedPayloadPatches[3], 14, 0, "yyyyy")
|
||||||
|
requireRangeChunk(t, m.streamedPayloadPatches[4], 10, 0, "zzzzz")
|
||||||
|
requireRangeChunk(t, m.streamedPayloadPatches[5], 10, 0, "zzzzz")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func requireRangeChunk(t *testing.T, pp *object.PayloadPatch, offset, length int, chunk string) {
|
func requireRangeChunk(t *testing.T, pp *object.PayloadPatch, offset, length int, chunk string) {
|
||||||
require.NotNil(t, pp)
|
require.NotNil(t, pp)
|
||||||
require.Equal(t, uint64(offset), pp.Range.GetOffset())
|
require.Equal(t, uint64(offset), pp.Range.GetOffset())
|
||||||
|
|
Loading…
Reference in a new issue