1
// Copyright 2022 The CubeFS Authors.
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
7
// http://www.apache.org/licenses/LICENSE-2.0
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12
// implied. See the License for the specific language governing
13
// permissions and limitations under the License.
23
"github.com/stretchr/testify/require"
25
"github.com/cubefs/cubefs/blobstore/common/codemode"
26
"github.com/cubefs/cubefs/blobstore/common/ec"
27
rp "github.com/cubefs/cubefs/blobstore/common/resourcepool"
28
_ "github.com/cubefs/cubefs/blobstore/testing/nolog"
39
var memPool = rp.NewMemPool(map[int]int{kb64: 1, mb: 1})
42
mrand.Seed(time.Now().Unix())
45
func TestNewBuffer(t *testing.T) {
46
cm := codemode.EC6P6.Tactic()
47
buffer, err := ec.NewBuffer(kb, cm, memPool)
48
require.NoError(t, err)
49
defer buffer.Release()
50
require.Equal(t, kb, len(buffer.DataBuf))
51
require.Equal(t, kb64, cap(buffer.DataBuf))
52
require.Equal(t, cap(buffer.ECDataBuf), cap(buffer.DataBuf))
55
cm = codemode.EC16P20L2.Tactic()
56
buffer, err = ec.NewBuffer(kb64, cm, memPool)
57
require.NoError(t, err)
58
defer buffer.Release()
59
require.Equal(t, kb64, len(buffer.DataBuf))
60
require.Equal(t, mb, cap(buffer.DataBuf))
61
require.Equal(t, cap(buffer.ECDataBuf), cap(buffer.DataBuf))
63
// alloc new bytes when no suitable pool, do not put back
64
buffer, err = ec.NewBuffer(kb512, cm, memPool)
65
shardSize := (kb512 + cm.N - 1) / cm.N
66
require.NoError(t, err)
67
require.Equal(t, kb512, len(buffer.DataBuf))
68
require.Equal(t, shardSize*(cm.N+cm.M+cm.L), cap(buffer.DataBuf))
69
require.Equal(t, shardSize*cm.N, len(buffer.ECDataBuf))
70
require.Equal(t, shardSize*(cm.N+cm.M+cm.L), cap(buffer.ECDataBuf))
73
func TestNewRangedBuffer(t *testing.T) {
74
cm := codemode.EC6P6.Tactic()
75
buffer, err := ec.NewBuffer(kb, cm, memPool)
76
require.NoError(t, err)
77
require.Equal(t, kb, len(buffer.DataBuf))
78
require.NotNil(t, buffer.ECDataBuf)
79
require.Equal(t, kb64, cap(buffer.DataBuf))
83
cm = codemode.EC16P20L2.Tactic()
84
buffer, err = ec.NewRangeBuffer(kb4, kb, 2*kb+2, cm, memPool)
85
require.NoError(t, err)
86
require.Equal(t, kb+2, len(buffer.DataBuf))
87
require.Nil(t, buffer.ECDataBuf)
88
require.Equal(t, kb64, cap(buffer.DataBuf))
92
func TestGetBufferSize(t *testing.T) {
93
cm := codemode.EC6P6.Tactic()
94
sizes, err := ec.GetBufferSizes(kb, cm)
95
shardSize := (kb + cm.N - 1) / cm.N
96
if shardSize < cm.MinShardSize {
97
shardSize = cm.MinShardSize
99
require.NoError(t, err)
100
require.Equal(t, shardSize, sizes.ShardSize)
101
require.Equal(t, kb, sizes.DataSize)
102
require.Equal(t, shardSize*cm.N, sizes.ECDataSize)
103
require.Equal(t, shardSize*(cm.N+cm.M+cm.L), sizes.ECSize)
105
cm = codemode.EC16P20L2.Tactic()
106
sizes, err = ec.GetBufferSizes(kb512, cm)
107
shardSize = (kb512 + cm.N - 1) / cm.N
108
if shardSize < cm.MinShardSize {
109
shardSize = cm.MinShardSize
111
require.NoError(t, err)
112
require.Equal(t, shardSize, sizes.ShardSize)
113
require.Equal(t, kb512, sizes.DataSize)
114
require.Equal(t, shardSize*cm.N, sizes.ECDataSize)
115
require.Equal(t, shardSize*(cm.N+cm.M+cm.L), sizes.ECSize)
117
_, err = ec.GetBufferSizes(0, cm)
118
require.ErrorIs(t, ec.ErrShortData, err)
119
_, err = ec.GetBufferSizes(-1, cm)
120
require.ErrorIs(t, ec.ErrShortData, err)
123
func TestBufferResize(t *testing.T) {
124
cm := codemode.EC6P6.Tactic()
125
buffer, err := ec.NewBuffer(kb, cm, memPool)
126
require.NoError(t, err)
130
require.Equal(t, kb, len(buffer.DataBuf))
131
require.Equal(t, kb64, cap(buffer.DataBuf))
134
// _, err = ec.NewBuffer(kb, cm, memPool)
135
// require.ErrorIs(t, rp.ErrPoolLimit, err)
137
err = buffer.Resize(kb + 512)
138
require.NoError(t, err)
139
require.Equal(t, kb+512, len(buffer.DataBuf))
140
require.Equal(t, kb64, cap(buffer.DataBuf))
143
// _, err = ec.NewBuffer(kb, cm, memPool)
144
// require.ErrorIs(t, rp.ErrPoolLimit, err)
146
// mb pool, release kb64 pool
147
err = buffer.Resize(kb64)
148
require.NoError(t, err)
149
require.Equal(t, kb64, len(buffer.DataBuf))
150
require.Equal(t, mb, cap(buffer.DataBuf))
152
// old kb64 pool was released
153
buff, err := ec.NewBuffer(kb, cm, memPool)
154
require.NoError(t, err)
158
func TestBufferRelease(t *testing.T) {
160
var buffer *ec.Buffer
161
require.NoError(t, buffer.Release())
164
buffer := &ec.Buffer{}
165
require.NoError(t, buffer.Release())
168
buffer, err := ec.NewBuffer(kb, codemode.EC6P6.Tactic(), memPool)
169
require.NoError(t, err)
170
require.NoError(t, buffer.Release())
174
func TestBufferDataPadding(t *testing.T) {
175
// new a mempool while resize will alloc oversize buffer
176
memPool := rp.NewMemPool(map[int]int{kb64: 1, mb: 1})
178
for _, size := range []int{kb64, mb} {
179
buf, err := memPool.Get(size)
180
require.NoError(t, err)
185
zero := make([]byte, mb)
187
cm := codemode.EC6P6.Tactic()
188
buffer, err := ec.NewBuffer(kb, cm, memPool)
189
require.NoError(t, err)
194
buf := buffer.DataBuf[:cap(buffer.DataBuf)]
195
require.Equal(t, zero[:buffer.ShardSize*cm.N-buffer.DataSize],
196
buf[buffer.DataSize:buffer.ShardSize*cm.N])
198
for ii := 0; ii < 100; ii++ {
199
err = buffer.Resize(mrand.Intn(mb*6) + 1)
200
require.NoError(t, err)
201
buf = buffer.DataBuf[:cap(buffer.DataBuf)]
202
require.Equal(t, zero[:buffer.ShardSize*cm.N-buffer.DataSize],
203
buf[buffer.DataSize:buffer.ShardSize*cm.N])