cubefs

Форк
0
/
server_test.go 
706 строк · 18.3 Кб
1
// Copyright 2022 The CubeFS Authors.
2
//
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
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
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.
14

15
package access
16

17
import (
18
	"bytes"
19
	"context"
20
	"encoding/json"
21
	"errors"
22
	"fmt"
23
	"io"
24
	"net/http"
25
	"net/http/httptest"
26
	"strconv"
27
	"sync"
28
	"testing"
29

30
	"github.com/golang/mock/gomock"
31
	"github.com/stretchr/testify/require"
32

33
	"github.com/cubefs/cubefs/blobstore/api/access"
34
	"github.com/cubefs/cubefs/blobstore/common/codemode"
35
	errcode "github.com/cubefs/cubefs/blobstore/common/errors"
36
	"github.com/cubefs/cubefs/blobstore/common/proto"
37
	"github.com/cubefs/cubefs/blobstore/common/rpc"
38
	"github.com/cubefs/cubefs/blobstore/common/uptoken"
39
)
40

41
var (
42
	ctx              = context.Background()
43
	_blobSize uint32 = 1 << 20
44
	location         = &access.Location{
45
		ClusterID: 1,
46
		CodeMode:  1,
47
		BlobSize:  _blobSize,
48
		Crc:       0,
49
		Blobs: []access.SliceInfo{{
50
			MinBid: 111,
51
			Vid:    1111,
52
			Count:  11,
53
		}},
54
	}
55

56
	testServer *httptest.Server
57
	once       sync.Once
58
)
59

60
func runMockService(s *Service) string {
61
	once.Do(func() {
62
		testServer = httptest.NewServer(NewHandler(s))
63
	})
64
	return testServer.URL
65
}
66

67
func newService() *Service {
68
	ctr := gomock.NewController(&testing.T{})
69
	s := NewMockStreamHandler(ctr)
70

71
	s.EXPECT().Alloc(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().DoAndReturn(
72
		func(ctx context.Context, size uint64, blobSize uint32,
73
			assignClusterID proto.ClusterID, codeMode codemode.CodeMode) (*access.Location, error) {
74
			if size < 1024 {
75
				return nil, errors.New("fake alloc location")
76
			}
77
			loc := location.Copy()
78
			loc.Size = uint64(size)
79
			fillCrc(&loc)
80
			return &loc, nil
81
		})
82

83
	s.EXPECT().PutAt(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(),
84
		gomock.Any()).AnyTimes().DoAndReturn(
85
		func(ctx context.Context, rc io.Reader,
86
			clusterID proto.ClusterID, vid proto.Vid, bid proto.BlobID, size int64,
87
			hasherMap access.HasherMap) error {
88
			if size < 1024 {
89
				return errcode.ErrAccessLimited
90
			}
91
			return nil
92
		})
93

94
	s.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().DoAndReturn(
95
		func(ctx context.Context, rc io.Reader, size int64, hasherMap access.HasherMap) (*access.Location, error) {
96
			if size < 1024 {
97
				return nil, errors.New("fake put nil body")
98
			}
99
			loc := location.Copy()
100
			loc.Size = uint64(size)
101
			fillCrc(&loc)
102
			return &loc, nil
103
		})
104

105
	s.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().DoAndReturn(
106
		func(ctx context.Context, w io.Writer, location access.Location, readSize, offset uint64) (func() error, error) {
107
			if readSize < 1024 {
108
				return nil, errors.New("fake get nil body")
109
			}
110
			return func() error { return nil }, nil
111
		})
112
	s.EXPECT().Delete(gomock.Any(), gomock.Any()).AnyTimes().DoAndReturn(
113
		func(ctx context.Context, location *access.Location) error {
114
			if location.ClusterID >= 10 {
115
				return errors.New("fake delete error with cluster")
116
			} else if location.ClusterID == 1 && location.Crc > 0 && location.Size < 1024 {
117
				return errors.New("fake delete error")
118
			}
119
			return nil
120
		})
121

122
	return &Service{
123
		streamHandler: s,
124
		limiter: NewLimiter(LimitConfig{
125
			NameRps: map[string]int{
126
				limitNameAlloc: 2,
127
			},
128
			ReaderMBps: 0,
129
			WriterMBps: 0,
130
		}),
131
	}
132
}
133

134
func newClient() rpc.Client {
135
	return rpc.NewClient(&rpc.Config{})
136
}
137

138
func TestAccessServiceNew(t *testing.T) {
139
	runMockService(newService())
140
}
141

142
func TestAccessServiceAlloc(t *testing.T) {
143
	host := runMockService(newService())
144
	cli := newClient()
145

146
	url := func() string {
147
		return fmt.Sprintf("%s/alloc", host)
148
	}
149
	args := access.AllocArgs{
150
		Size:            0,
151
		BlobSize:        0,
152
		AssignClusterID: 0,
153
		CodeMode:        0,
154
	}
155
	{
156
		resp := &access.AllocResp{}
157
		err := cli.PostWith(ctx, url(), resp, args)
158
		assertErrorCode(t, 400, err)
159
	}
160
	{
161
		args.Size = 1023
162
		resp := &access.AllocResp{}
163
		err := cli.PostWith(ctx, url(), resp, args)
164
		assertErrorCode(t, 500, err)
165
	}
166
	{
167
		args.Size = 1024
168
		resp := &access.AllocResp{}
169
		err := cli.PostWith(ctx, url(), resp, args)
170
		require.NoError(t, err)
171
		require.Equal(t, uint64(1024), resp.Location.Size)
172
	}
173
	{
174
		args.Size = uint64(_blobSize)
175
		resp := &access.AllocResp{}
176
		err := cli.PostWith(ctx, url(), resp, args)
177
		require.NoError(t, err)
178
		require.Equal(t, uint64(_blobSize), resp.Location.Size)
179
	}
180
	{
181
		args.Size = uint64(_blobSize) + 1
182
		resp := &access.AllocResp{}
183
		err := cli.PostWith(ctx, url(), resp, args)
184
		require.NoError(t, err)
185
		require.Equal(t, uint64(_blobSize)+1, resp.Location.Size)
186
	}
187
}
188

189
func TestAccessServicePutAt(t *testing.T) {
190
	host := runMockService(newService())
191
	cli := newClient()
192

193
	url := func(size int64, token string) string {
194
		return fmt.Sprintf("%s/putat?clusterid=1&volumeid=1111&blobid=111&size=%d&hashes=14&token=%s",
195
			host, size, token)
196
	}
197

198
	for _, method := range []string{http.MethodPut, http.MethodPost} {
199
		args := access.PutArgs{
200
			Size: 0,
201
		}
202
		{
203
			buf := make([]byte, args.Size)
204
			req, _ := http.NewRequest(method, url(args.Size, ""), bytes.NewReader(buf))
205
			resp := &access.PutAtResp{}
206
			err := cli.DoWith(ctx, req, resp, rpc.WithCrcEncode())
207
			assertErrorCode(t, 400, err)
208
		}
209
		{
210
			args.Size = 1023
211
			buf := make([]byte, args.Size)
212
			req, _ := http.NewRequest(method, url(args.Size, ""), bytes.NewReader(buf))
213
			resp := &access.PutAtResp{}
214
			err := cli.DoWith(ctx, req, resp, rpc.WithCrcEncode())
215
			assertErrorCode(t, 400, err)
216
		}
217
		{
218
			args.Size = 1023
219
			buf := make([]byte, args.Size)
220
			resp := &access.PutAtResp{}
221
			req, _ := http.NewRequest(method, url(args.Size, "c1fdcecaacbfafd86f0b00"), bytes.NewReader(buf))
222
			err := cli.DoWith(ctx, req, resp, rpc.WithCrcEncode())
223
			assertErrorCode(t, 552, err)
224
		}
225
		{
226
			args.Size = 1024
227
			buf := make([]byte, args.Size)
228
			req, _ := http.NewRequest(method, url(args.Size, "8238436d05ecf2366f0b00"), bytes.NewReader(buf))
229
			resp := &access.PutAtResp{}
230
			err := cli.DoWith(ctx, req, resp, rpc.WithCrcEncode())
231
			require.NoError(t, err)
232

233
			req, _ = http.NewRequest(method, url(args.Size, "1238436d05ecf2366f0b00"), bytes.NewReader(buf))
234
			err = cli.DoWith(ctx, req, resp, rpc.WithCrcEncode())
235
			assertErrorCode(t, 400, err)
236
		}
237
	}
238
}
239

240
func TestAccessServicePut(t *testing.T) {
241
	host := runMockService(newService())
242
	cli := newClient()
243

244
	url := func(size int64, hashes access.HashAlgorithm) string {
245
		return fmt.Sprintf("%s/put?size=%d&hashes=%d", host, size, hashes)
246
	}
247

248
	for _, method := range []string{http.MethodPut, http.MethodPost} {
249
		args := access.PutArgs{
250
			Size:   0,
251
			Hashes: 14,
252
			Body:   nil,
253
		}
254
		{
255
			req, _ := http.NewRequest(method, fmt.Sprintf("%s/put?size=size", host), args.Body)
256
			resp := &access.PutResp{}
257
			err := cli.DoWith(ctx, req, resp, rpc.WithCrcEncode())
258
			assertErrorCode(t, 400, err)
259
		}
260
		{
261
			req, _ := http.NewRequest(method, url(args.Size, args.Hashes), args.Body)
262
			resp := &access.PutResp{}
263
			err := cli.DoWith(ctx, req, resp, rpc.WithCrcEncode())
264
			assertErrorCode(t, 400, err)
265
		}
266
		{
267
			args.Body = bytes.NewReader(make([]byte, 1023))
268
			req, _ := http.NewRequest(method, url(1023, args.Hashes), args.Body)
269
			resp := &access.PutResp{}
270
			err := cli.DoWith(ctx, req, resp, rpc.WithCrcEncode())
271
			assertErrorCode(t, 500, err)
272
		}
273
		{
274
			args.Body = bytes.NewReader(make([]byte, 1024))
275
			req, _ := http.NewRequest(method, url(1024, args.Hashes), args.Body)
276
			resp := &access.PutResp{}
277
			err := cli.DoWith(ctx, req, resp, rpc.WithCrcEncode())
278
			require.NoError(t, err)
279
			require.Equal(t, uint64(1024), resp.Location.Size)
280
		}
281
	}
282
}
283

284
func TestAccessServiceGet(t *testing.T) {
285
	host := runMockService(newService())
286
	cli := newClient()
287

288
	url := func() string {
289
		return fmt.Sprintf("%s/get", host)
290
	}
291
	args := access.GetArgs{
292
		Location: location.Copy(),
293
		Offset:   0,
294
		ReadSize: 0,
295
	}
296
	{
297
		args.ReadSize = 10
298
		resp, err := cli.Post(ctx, url(), args)
299
		require.NoError(t, err)
300
		resp.Body.Close()
301
		require.Equal(t, 400, resp.StatusCode, resp.Status)
302
	}
303
	{
304
		args.Location.Size = 1023
305
		args.ReadSize = 1023
306
		fillCrc(&args.Location)
307
		resp, err := cli.Post(ctx, url(), args)
308
		require.NoError(t, err)
309
		resp.Body.Close()
310
		require.Equal(t, 500, resp.StatusCode, resp.Status)
311
	}
312
	{
313
		args.Location.Size = 1024
314
		args.ReadSize = 1024
315
		fillCrc(&args.Location)
316
		resp, err := cli.Post(ctx, url(), args)
317
		require.NoError(t, err)
318
		resp.Body.Close()
319
		require.Equal(t, 200, resp.StatusCode, resp.Status)
320
	}
321
	{
322
		args.Location.Size = 10240
323
		args.Offset = 1000
324
		args.ReadSize = 1024
325
		fillCrc(&args.Location)
326
		resp, err := cli.Post(ctx, url(), args)
327
		require.NoError(t, err)
328
		resp.Body.Close()
329
		require.Equal(t, 206, resp.StatusCode, resp.Status)
330
	}
331
}
332

333
func TestAccessServiceDelete(t *testing.T) {
334
	host := runMockService(newService())
335
	cli := newClient()
336

337
	url := fmt.Sprintf("%s/delete", host)
338
	deleteRequest := func(args interface{}) (code int, ret access.DeleteResp, err error) {
339
		resp, err := cli.Post(ctx, url, args)
340
		if err != nil {
341
			return
342
		}
343
		defer resp.Body.Close()
344

345
		code = resp.StatusCode
346
		if code/100 == 2 {
347
			size, _ := strconv.Atoi(resp.Header.Get("Content-Length"))
348
			buf := make([]byte, size)
349
			_, err = io.ReadFull(resp.Body, buf)
350
			if err != nil {
351
				return
352
			}
353
			if err = json.Unmarshal(buf, &ret); err != nil {
354
				return
355
			}
356
		}
357
		if code >= 400 {
358
			err = rpc.NewError(code, "Code", fmt.Errorf("httpcode: %d", code))
359
			return
360
		}
361
		return
362
	}
363

364
	args := access.DeleteArgs{
365
		Locations: []access.Location{location.Copy()},
366
	}
367
	{
368
		code, _, err := deleteRequest(access.DeleteArgs{})
369
		require.Error(t, err)
370
		require.Equal(t, 400, code)
371
	}
372
	{
373
		code, _, err := deleteRequest(args)
374
		require.Error(t, err)
375
		require.Equal(t, 400, code)
376
	}
377
	{
378
		fillCrc(&args.Locations[0])
379
		code, resp, err := deleteRequest(args)
380
		require.NoError(t, err)
381
		require.Equal(t, 226, code)
382
		require.Equal(t, args.Locations[0], resp.FailedLocations[0])
383
	}
384
	{
385
		loc := &args.Locations[0]
386
		loc.Size = 1024
387
		fillCrc(loc)
388
		code, _, err := deleteRequest(args)
389
		require.NoError(t, err)
390
		require.Equal(t, 200, code)
391
	}
392
	{
393
		loc := location.Copy()
394
		loc.Size = 1024
395
		fillCrc(&loc)
396
		locs := make([]access.Location, access.MaxDeleteLocations)
397
		for idx := range locs {
398
			locs[idx] = loc
399
		}
400
		code, resp, err := deleteRequest(access.DeleteArgs{Locations: locs})
401
		require.NoError(t, err)
402
		require.Equal(t, 200, code)
403
		require.Equal(t, 0, len(resp.FailedLocations))
404
	}
405
	{
406
		loc := location.Copy()
407
		loc.Size = 1024
408
		fillCrc(&loc)
409
		locs := make([]access.Location, access.MaxDeleteLocations+1)
410
		for idx := range locs {
411
			locs[idx] = loc
412
		}
413
		code, _, err := deleteRequest(access.DeleteArgs{Locations: locs})
414
		require.Error(t, err)
415
		require.Equal(t, 400, code)
416
	}
417
	{
418
		loc := location.Copy()
419
		loc.Size = 1024
420
		loc.ClusterID = proto.ClusterID(11)
421
		fillCrc(&loc)
422
		code, resp, err := deleteRequest(access.DeleteArgs{Locations: []access.Location{loc}})
423
		require.NoError(t, err)
424
		require.Equal(t, 226, code)
425
		require.Equal(t, 1, len(resp.FailedLocations))
426
		require.Equal(t, proto.ClusterID(11), resp.FailedLocations[0].ClusterID)
427
	}
428
	{
429
		locs := make([]access.Location, access.MaxDeleteLocations)
430
		for idx := range locs {
431
			loc := location.Copy()
432
			loc.Size = 1024
433
			loc.ClusterID = proto.ClusterID(idx % 11)
434
			fillCrc(&loc)
435
			locs[idx] = loc
436
		}
437
		code, resp, err := deleteRequest(access.DeleteArgs{Locations: locs})
438
		require.NoError(t, err)
439
		require.Equal(t, 226, code)
440
		require.Equal(t, 93, len(resp.FailedLocations))
441
	}
442
}
443

444
func TestAccessServiceDeleteBlob(t *testing.T) {
445
	host := runMockService(newService())
446
	cli := newClient()
447

448
	url := func(size int64, token string) string {
449
		return fmt.Sprintf("%s/deleteblob?clusterid=1&volumeid=1111&blobid=111&size=%d&token=%s",
450
			host, size, token)
451
	}
452

453
	method := http.MethodDelete
454
	args := access.PutArgs{
455
		Size: 0,
456
	}
457
	{
458
		req, _ := http.NewRequest(method, url(args.Size, "xxx"), nil)
459
		err := cli.DoWith(ctx, req, nil)
460
		assertErrorCode(t, 400, err)
461
	}
462
	{
463
		req, _ := http.NewRequest(method, url(args.Size, ""), nil)
464
		err := cli.DoWith(ctx, req, nil)
465
		assertErrorCode(t, 400, err)
466
	}
467
	{
468
		args.Size = 1023
469
		req, _ := http.NewRequest(method, url(args.Size, ""), nil)
470
		err := cli.DoWith(ctx, req, nil)
471
		assertErrorCode(t, 400, err)
472
	}
473
	{
474
		args.Size = 1023
475
		req, _ := http.NewRequest(method, url(args.Size, "xxx"), nil)
476
		err := cli.DoWith(ctx, req, nil)
477
		assertErrorCode(t, 400, err)
478
	}
479
	{
480
		args.Size = 1023
481
		req, _ := http.NewRequest(method, url(args.Size, "c1fdcecaacbfafd86f0b00"), nil)
482
		err := cli.DoWith(ctx, req, nil)
483
		require.NoError(t, err)
484
	}
485

486
	{
487
		url := func() string {
488
			return fmt.Sprintf("%s/deleteblob?clusterid=11&volumeid=1111&blobid=111&size=%d&token=%s",
489
				host, 1024, "f034db4503d5dc3f6f0100")
490
		}
491
		req, _ := http.NewRequest(method, url(), nil)
492
		err := cli.DoWith(ctx, req, nil)
493
		assertErrorCode(t, 500, err)
494
	}
495
}
496

497
func TestAccessServiceSign(t *testing.T) {
498
	host := runMockService(newService())
499
	cli := newClient()
500

501
	url := func() string {
502
		return fmt.Sprintf("%s/sign", host)
503
	}
504
	args := access.SignArgs{
505
		Locations: []access.Location{location.Copy()},
506
		Location:  location.Copy(),
507
	}
508
	{
509
		resp := &access.SignResp{}
510
		err := cli.PostWith(ctx, url(), resp, access.SignArgs{})
511
		assertErrorCode(t, 400, err)
512
	}
513
	{
514
		resp := &access.SignResp{}
515
		err := cli.PostWith(ctx, url(), resp, args)
516
		assertErrorCode(t, 400, err)
517
	}
518
	{
519
		fillCrc(&args.Locations[0])
520
		resp := &access.SignResp{}
521
		err := cli.PostWith(ctx, url(), resp, args)
522
		require.NoError(t, err)
523
	}
524
}
525

526
func assertErrorCode(t *testing.T, code int, err error) {
527
	require.Error(t, err)
528
	codeActual := rpc.DetectStatusCode(err)
529
	require.Equal(t, code, codeActual, err.Error())
530
}
531

532
func TestAccessServiceTokens(t *testing.T) {
533
	skey := tokenSecretKeys[0][:]
534
	checker := func(loc *access.Location, tokens []string) {
535
		if loc.Size == 0 {
536
			require.Equal(t, 0, len(tokens))
537
			return
538
		}
539

540
		hasMultiBlobs := loc.Size >= uint64(loc.BlobSize)
541
		lastSize := uint32(loc.Size % uint64(loc.BlobSize))
542
		if !hasMultiBlobs {
543
			require.Equal(t, 1, len(tokens))
544

545
			token := uptoken.DecodeToken(tokens[0])
546
			blob := loc.Blobs[0]
547
			for bid := blob.MinBid - 100; bid < blob.MinBid+100; bid++ {
548
				require.False(t, token.IsValid(loc.ClusterID, blob.Vid, bid, loc.BlobSize, skey))
549
			}
550
			require.True(t, token.IsValid(loc.ClusterID, blob.Vid, blob.MinBid, lastSize, skey))
551
			return
552
		}
553

554
		if lastSize == 0 {
555
			require.Equal(t, len(loc.Blobs), len(tokens))
556
			for idx, blob := range loc.Blobs {
557
				token := uptoken.DecodeToken(tokens[idx])
558
				for ii := uint32(0); ii < 100; ii++ {
559
					bid := blob.MinBid - proto.BlobID(ii) - 1
560
					require.False(t, token.IsValid(loc.ClusterID, blob.Vid, bid, loc.BlobSize, skey))
561
					bid = blob.MinBid + proto.BlobID(blob.Count+ii)
562
					require.False(t, token.IsValid(loc.ClusterID, blob.Vid, bid, loc.BlobSize, skey))
563
				}
564
				for ii := uint32(0); ii < blob.Count; ii++ {
565
					bid := blob.MinBid + proto.BlobID(ii)
566
					require.True(t, token.IsValid(loc.ClusterID, blob.Vid, bid, loc.BlobSize, skey))
567
				}
568
			}
569
			return
570
		}
571

572
		require.Equal(t, len(loc.Blobs)+1, len(tokens))
573
		for ii := 0; ii < len(loc.Blobs)-1; ii++ {
574
			token := uptoken.DecodeToken(tokens[ii])
575
			blob := loc.Blobs[ii]
576
			for ii := uint32(0); ii < blob.Count; ii++ {
577
				bid := blob.MinBid + proto.BlobID(ii)
578
				require.True(t, token.IsValid(loc.ClusterID, blob.Vid, bid, loc.BlobSize, skey))
579
			}
580
		}
581

582
		token := uptoken.DecodeToken(tokens[len(loc.Blobs)-1])
583
		blob := loc.Blobs[len(loc.Blobs)-1]
584
		for ii := uint32(0); ii < 100; ii++ {
585
			bid := blob.MinBid - proto.BlobID(ii) - 1
586
			require.False(t, token.IsValid(loc.ClusterID, blob.Vid, bid, loc.BlobSize, skey))
587
			bid = blob.MinBid + proto.BlobID(blob.Count+ii) - 1
588
			require.False(t, token.IsValid(loc.ClusterID, blob.Vid, bid, loc.BlobSize, skey))
589
		}
590
		for ii := uint32(0); ii < blob.Count-1; ii++ {
591
			bid := blob.MinBid + proto.BlobID(ii)
592
			require.True(t, token.IsValid(loc.ClusterID, blob.Vid, bid, loc.BlobSize, skey))
593
		}
594

595
		token = uptoken.DecodeToken(tokens[len(loc.Blobs)])
596
		lastbid := blob.MinBid + proto.BlobID(blob.Count) - 1
597
		require.True(t, token.IsValid(loc.ClusterID, blob.Vid, lastbid, lastSize, skey))
598
	}
599

600
	{
601
		loc := &access.Location{
602
			Size:     0,
603
			BlobSize: 333,
604
			Blobs:    []access.SliceInfo{},
605
		}
606
		checker(loc, genTokens(loc))
607
	}
608
	{
609
		loc := &access.Location{
610
			Size:     1,
611
			BlobSize: 1024,
612
			Blobs: []access.SliceInfo{
613
				{MinBid: 100, Vid: 1000, Count: 1},
614
			},
615
		}
616
		checker(loc, genTokens(loc))
617
	}
618
	{
619
		loc := &access.Location{
620
			Size:     1024,
621
			BlobSize: 1024,
622
			Blobs: []access.SliceInfo{
623
				{MinBid: 100, Vid: 1000, Count: 1},
624
			},
625
		}
626
		checker(loc, genTokens(loc))
627
	}
628
	{
629
		loc := &access.Location{
630
			Size:     1025,
631
			BlobSize: 1024,
632
			Blobs: []access.SliceInfo{
633
				{MinBid: 100, Vid: 1000, Count: 2},
634
			},
635
		}
636
		checker(loc, genTokens(loc))
637
	}
638
	{
639
		loc := &access.Location{
640
			Size:     2048,
641
			BlobSize: 1024,
642
			Blobs: []access.SliceInfo{
643
				{MinBid: 100, Vid: 1000, Count: 2},
644
			},
645
		}
646
		checker(loc, genTokens(loc))
647
	}
648
	{
649
		loc := &access.Location{
650
			Size:     10240,
651
			BlobSize: 1024,
652
			Blobs: []access.SliceInfo{
653
				{MinBid: 100, Vid: 1000, Count: 4},
654
				{MinBid: 200, Vid: 1000, Count: 6},
655
			},
656
		}
657
		checker(loc, genTokens(loc))
658
	}
659
	{
660
		loc := &access.Location{
661
			Size:     1025,
662
			BlobSize: 1024,
663
			Blobs: []access.SliceInfo{
664
				{MinBid: 100, Vid: 1000, Count: 1},
665
				{MinBid: 200, Vid: 1000, Count: 1},
666
			},
667
		}
668
		checker(loc, genTokens(loc))
669
	}
670
	{
671
		loc := &access.Location{
672
			Size:     10242,
673
			BlobSize: 1024,
674
			Blobs: []access.SliceInfo{
675
				{MinBid: 100, Vid: 1000, Count: 5},
676
				{MinBid: 200, Vid: 1000, Count: 6},
677
			},
678
		}
679
		checker(loc, genTokens(loc))
680
	}
681
}
682

683
func TestAccessServiceLimited(t *testing.T) {
684
	host := runMockService(newService())
685
	cli := newClient()
686

687
	url := func() string {
688
		return fmt.Sprintf("%s/alloc", host)
689
	}
690
	args := access.AllocArgs{Size: 1024}
691
	var wg sync.WaitGroup
692
	wg.Add(100)
693
	for i := 0; i < 100; i++ {
694
		go func() {
695
			defer wg.Done()
696
			resp := &access.AllocResp{}
697
			err := cli.PostWith(ctx, url(), resp, args)
698
			if err != nil {
699
				assertErrorCode(t, errcode.CodeAccessLimited, err)
700
			} else {
701
				require.Equal(t, uint64(1024), resp.Location.Size)
702
			}
703
		}()
704
	}
705
	wg.Wait()
706
}
707

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.