Dragonfly2
528 строк · 14.3 Кб
1/*
2* Copyright 2020 The Dragonfly Authors
3*
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at
7*
8* http://www.apache.org/licenses/LICENSE-2.0
9*
10* Unless required by applicable law or agreed to in writing, software
11* distributed under the License is distributed on an "AS IS" BASIS,
12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13* See the License for the specific language governing permissions and
14* limitations under the License.
15*/
16
17package resource
18
19import (
20"errors"
21"reflect"
22"testing"
23"time"
24
25"github.com/stretchr/testify/assert"
26gomock "go.uber.org/mock/gomock"
27
28commonv2 "d7y.io/api/v2/pkg/apis/common/v2"
29
30"d7y.io/dragonfly/v2/pkg/container/set"
31"d7y.io/dragonfly/v2/pkg/gc"
32"d7y.io/dragonfly/v2/scheduler/config"
33)
34
35var (
36mockHostGCConfig = &config.GCConfig{
37HostGCInterval: 1 * time.Second,
38}
39)
40
41func TestHostManager_newHostManager(t *testing.T) {
42tests := []struct {
43name string
44mock func(m *gc.MockGCMockRecorder)
45expect func(t *testing.T, hostManager HostManager, err error)
46}{
47{
48name: "new host manager",
49mock: func(m *gc.MockGCMockRecorder) {
50m.Add(gomock.Any()).Return(nil).Times(1)
51},
52expect: func(t *testing.T, hostManager HostManager, err error) {
53assert := assert.New(t)
54assert.Equal(reflect.TypeOf(hostManager).Elem().Name(), "hostManager")
55},
56},
57{
58name: "new host manager failed because of gc error",
59mock: func(m *gc.MockGCMockRecorder) {
60m.Add(gomock.Any()).Return(errors.New("foo")).Times(1)
61},
62expect: func(t *testing.T, hostManager HostManager, err error) {
63assert := assert.New(t)
64assert.EqualError(err, "foo")
65},
66},
67}
68
69for _, tc := range tests {
70t.Run(tc.name, func(t *testing.T) {
71ctl := gomock.NewController(t)
72defer ctl.Finish()
73gc := gc.NewMockGC(ctl)
74tc.mock(gc.EXPECT())
75hostManager, err := newHostManager(mockHostGCConfig, gc)
76
77tc.expect(t, hostManager, err)
78})
79}
80}
81
82func TestHostManager_Load(t *testing.T) {
83tests := []struct {
84name string
85mock func(m *gc.MockGCMockRecorder)
86expect func(t *testing.T, hostManager HostManager, mockHost *Host)
87}{
88{
89name: "load host",
90mock: func(m *gc.MockGCMockRecorder) {
91m.Add(gomock.Any()).Return(nil).Times(1)
92},
93expect: func(t *testing.T, hostManager HostManager, mockHost *Host) {
94assert := assert.New(t)
95hostManager.Store(mockHost)
96host, loaded := hostManager.Load(mockHost.ID)
97assert.Equal(loaded, true)
98assert.Equal(host.ID, mockHost.ID)
99},
100},
101{
102name: "host does not exist",
103mock: func(m *gc.MockGCMockRecorder) {
104m.Add(gomock.Any()).Return(nil).Times(1)
105},
106expect: func(t *testing.T, hostManager HostManager, mockHost *Host) {
107assert := assert.New(t)
108_, loaded := hostManager.Load(mockHost.ID)
109assert.Equal(loaded, false)
110},
111},
112{
113name: "load key is empty",
114mock: func(m *gc.MockGCMockRecorder) {
115m.Add(gomock.Any()).Return(nil).Times(1)
116},
117expect: func(t *testing.T, hostManager HostManager, mockHost *Host) {
118assert := assert.New(t)
119mockHost.ID = ""
120hostManager.Store(mockHost)
121host, loaded := hostManager.Load(mockHost.ID)
122assert.Equal(loaded, true)
123assert.Equal(host.ID, mockHost.ID)
124},
125},
126}
127
128for _, tc := range tests {
129t.Run(tc.name, func(t *testing.T) {
130ctl := gomock.NewController(t)
131defer ctl.Finish()
132gc := gc.NewMockGC(ctl)
133tc.mock(gc.EXPECT())
134
135mockHost := NewHost(
136mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
137mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
138hostManager, err := newHostManager(mockHostGCConfig, gc)
139if err != nil {
140t.Fatal(err)
141}
142
143tc.expect(t, hostManager, mockHost)
144})
145}
146}
147
148func TestHostManager_Store(t *testing.T) {
149tests := []struct {
150name string
151mock func(m *gc.MockGCMockRecorder)
152expect func(t *testing.T, hostManager HostManager, mockHost *Host)
153}{
154{
155name: "store host",
156mock: func(m *gc.MockGCMockRecorder) {
157m.Add(gomock.Any()).Return(nil).Times(1)
158},
159expect: func(t *testing.T, hostManager HostManager, mockHost *Host) {
160assert := assert.New(t)
161hostManager.Store(mockHost)
162host, loaded := hostManager.Load(mockHost.ID)
163assert.Equal(loaded, true)
164assert.Equal(host.ID, mockHost.ID)
165},
166},
167{
168name: "store key is empty",
169mock: func(m *gc.MockGCMockRecorder) {
170m.Add(gomock.Any()).Return(nil).Times(1)
171},
172expect: func(t *testing.T, hostManager HostManager, mockHost *Host) {
173assert := assert.New(t)
174mockHost.ID = ""
175hostManager.Store(mockHost)
176host, loaded := hostManager.Load(mockHost.ID)
177assert.Equal(loaded, true)
178assert.Equal(host.ID, mockHost.ID)
179},
180},
181}
182
183for _, tc := range tests {
184t.Run(tc.name, func(t *testing.T) {
185ctl := gomock.NewController(t)
186defer ctl.Finish()
187gc := gc.NewMockGC(ctl)
188tc.mock(gc.EXPECT())
189
190mockHost := NewHost(
191mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
192mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
193hostManager, err := newHostManager(mockHostGCConfig, gc)
194if err != nil {
195t.Fatal(err)
196}
197
198tc.expect(t, hostManager, mockHost)
199})
200}
201}
202
203func TestHostManager_LoadOrStore(t *testing.T) {
204tests := []struct {
205name string
206mock func(m *gc.MockGCMockRecorder)
207expect func(t *testing.T, hostManager HostManager, mockHost *Host)
208}{
209{
210name: "load host exist",
211mock: func(m *gc.MockGCMockRecorder) {
212m.Add(gomock.Any()).Return(nil).Times(1)
213},
214expect: func(t *testing.T, hostManager HostManager, mockHost *Host) {
215assert := assert.New(t)
216hostManager.Store(mockHost)
217host, loaded := hostManager.LoadOrStore(mockHost)
218assert.Equal(loaded, true)
219assert.Equal(host.ID, mockHost.ID)
220},
221},
222{
223name: "load host does not exist",
224mock: func(m *gc.MockGCMockRecorder) {
225m.Add(gomock.Any()).Return(nil).Times(1)
226},
227expect: func(t *testing.T, hostManager HostManager, mockHost *Host) {
228assert := assert.New(t)
229host, loaded := hostManager.LoadOrStore(mockHost)
230assert.Equal(loaded, false)
231assert.Equal(host.ID, mockHost.ID)
232},
233},
234}
235
236for _, tc := range tests {
237t.Run(tc.name, func(t *testing.T) {
238ctl := gomock.NewController(t)
239defer ctl.Finish()
240gc := gc.NewMockGC(ctl)
241tc.mock(gc.EXPECT())
242
243mockHost := NewHost(
244mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
245mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
246hostManager, err := newHostManager(mockHostGCConfig, gc)
247if err != nil {
248t.Fatal(err)
249}
250
251tc.expect(t, hostManager, mockHost)
252})
253}
254}
255
256func TestHostManager_Delete(t *testing.T) {
257tests := []struct {
258name string
259mock func(m *gc.MockGCMockRecorder)
260expect func(t *testing.T, hostManager HostManager, mockHost *Host)
261}{
262{
263name: "delete host",
264mock: func(m *gc.MockGCMockRecorder) {
265m.Add(gomock.Any()).Return(nil).Times(1)
266},
267expect: func(t *testing.T, hostManager HostManager, mockHost *Host) {
268assert := assert.New(t)
269hostManager.Store(mockHost)
270hostManager.Delete(mockHost.ID)
271_, loaded := hostManager.Load(mockHost.ID)
272assert.Equal(loaded, false)
273},
274},
275{
276name: "delete key does not exist",
277mock: func(m *gc.MockGCMockRecorder) {
278m.Add(gomock.Any()).Return(nil).Times(1)
279},
280expect: func(t *testing.T, hostManager HostManager, mockHost *Host) {
281assert := assert.New(t)
282mockHost.ID = ""
283hostManager.Store(mockHost)
284hostManager.Delete(mockHost.ID)
285_, loaded := hostManager.Load(mockHost.ID)
286assert.Equal(loaded, false)
287},
288},
289}
290
291for _, tc := range tests {
292t.Run(tc.name, func(t *testing.T) {
293ctl := gomock.NewController(t)
294defer ctl.Finish()
295gc := gc.NewMockGC(ctl)
296tc.mock(gc.EXPECT())
297
298mockHost := NewHost(
299mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
300mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
301hostManager, err := newHostManager(mockHostGCConfig, gc)
302if err != nil {
303t.Fatal(err)
304}
305
306tc.expect(t, hostManager, mockHost)
307})
308}
309}
310
311func TestHostManager_LoadRandomHosts(t *testing.T) {
312tests := []struct {
313name string
314hosts []*Host
315mock func(m *gc.MockGCMockRecorder)
316expect func(t *testing.T, hm HostManager, hosts []*Host)
317}{
318{
319name: "load random hosts",
320hosts: []*Host{
321NewHost(
322mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
323mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type),
324NewHost(
325mockRawSeedHost.ID, mockRawSeedHost.IP, mockRawSeedHost.Hostname,
326mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type),
327},
328mock: func(m *gc.MockGCMockRecorder) {
329m.Add(gomock.Any()).Return(nil).Times(1)
330},
331expect: func(t *testing.T, hm HostManager, hosts []*Host) {
332assert := assert.New(t)
333for _, host := range hosts {
334hm.Store(host)
335}
336
337blocklist := set.NewSafeSet[string]()
338blocklist.Add(mockRawSeedHost.ID)
339h := hm.LoadRandomHosts(2, blocklist)
340assert.Equal(len(h), 1)
341},
342},
343{
344name: "load random hosts when the load number is 0",
345hosts: []*Host{
346NewHost(
347mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
348mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type),
349NewHost(
350mockRawSeedHost.ID, mockRawSeedHost.IP, mockRawSeedHost.Hostname,
351mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type),
352},
353mock: func(m *gc.MockGCMockRecorder) {
354m.Add(gomock.Any()).Return(nil).Times(1)
355},
356expect: func(t *testing.T, hm HostManager, hosts []*Host) {
357assert := assert.New(t)
358for _, host := range hosts {
359hm.Store(host)
360}
361
362blocklist := set.NewSafeSet[string]()
363blocklist.Add(mockRawSeedHost.ID)
364h := hm.LoadRandomHosts(0, blocklist)
365assert.Equal(len(h), 0)
366},
367},
368{
369name: "map is empty",
370hosts: []*Host{},
371mock: func(m *gc.MockGCMockRecorder) {
372m.Add(gomock.Any()).Return(nil).Times(1)
373},
374expect: func(t *testing.T, hm HostManager, hosts []*Host) {
375assert := assert.New(t)
376for _, host := range hosts {
377hm.Store(host)
378}
379
380blocklist := set.NewSafeSet[string]()
381blocklist.Add(mockRawSeedHost.ID)
382h := hm.LoadRandomHosts(1, blocklist)
383assert.Equal(len(h), 0)
384},
385},
386{
387name: "the number of hosts in the map is insufficient",
388hosts: []*Host{
389NewHost(
390mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
391mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type),
392NewHost(
393mockRawSeedHost.ID, mockRawSeedHost.IP, mockRawSeedHost.Hostname,
394mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type),
395},
396mock: func(m *gc.MockGCMockRecorder) {
397m.Add(gomock.Any()).Return(nil).Times(1)
398},
399expect: func(t *testing.T, hm HostManager, hosts []*Host) {
400assert := assert.New(t)
401for _, host := range hosts {
402hm.Store(host)
403}
404
405blocklist := set.NewSafeSet[string]()
406blocklist.Add(mockRawSeedHost.ID)
407h := hm.LoadRandomHosts(3, blocklist)
408assert.Equal(len(h), 1)
409},
410},
411}
412
413for _, tc := range tests {
414t.Run(tc.name, func(t *testing.T) {
415ctl := gomock.NewController(t)
416defer ctl.Finish()
417gc := gc.NewMockGC(ctl)
418tc.mock(gc.EXPECT())
419
420hm, err := newHostManager(mockHostGCConfig, gc)
421if err != nil {
422t.Fatal(err)
423}
424
425tc.expect(t, hm, tc.hosts)
426})
427}
428}
429
430func TestHostManager_RunGC(t *testing.T) {
431tests := []struct {
432name string
433mock func(m *gc.MockGCMockRecorder)
434expect func(t *testing.T, hostManager HostManager, mockHost *Host, mockPeer *Peer)
435}{
436{
437name: "host reclaimed",
438mock: func(m *gc.MockGCMockRecorder) {
439m.Add(gomock.Any()).Return(nil).Times(1)
440},
441expect: func(t *testing.T, hostManager HostManager, mockHost *Host, mockPeer *Peer) {
442assert := assert.New(t)
443hostManager.Store(mockHost)
444err := hostManager.RunGC()
445assert.NoError(err)
446
447_, loaded := hostManager.Load(mockHost.ID)
448assert.Equal(loaded, false)
449},
450},
451{
452name: "host has peers",
453mock: func(m *gc.MockGCMockRecorder) {
454m.Add(gomock.Any()).Return(nil).Times(1)
455},
456expect: func(t *testing.T, hostManager HostManager, mockHost *Host, mockPeer *Peer) {
457assert := assert.New(t)
458hostManager.Store(mockHost)
459mockHost.StorePeer(mockPeer)
460err := hostManager.RunGC()
461assert.NoError(err)
462
463host, loaded := hostManager.Load(mockHost.ID)
464assert.Equal(loaded, true)
465assert.Equal(host.ID, mockHost.ID)
466},
467},
468{
469name: "host has upload peers",
470mock: func(m *gc.MockGCMockRecorder) {
471m.Add(gomock.Any()).Return(nil).Times(1)
472},
473expect: func(t *testing.T, hostManager HostManager, mockHost *Host, mockPeer *Peer) {
474assert := assert.New(t)
475hostManager.Store(mockHost)
476mockHost.StorePeer(mockPeer)
477mockHost.PeerCount.Add(0)
478mockHost.ConcurrentUploadCount.Add(1)
479err := hostManager.RunGC()
480assert.NoError(err)
481
482host, loaded := hostManager.Load(mockHost.ID)
483assert.Equal(loaded, true)
484assert.Equal(host.ID, mockHost.ID)
485},
486},
487{
488name: "host is seed peer",
489mock: func(m *gc.MockGCMockRecorder) {
490m.Add(gomock.Any()).Return(nil).Times(1)
491},
492expect: func(t *testing.T, hostManager HostManager, mockHost *Host, mockPeer *Peer) {
493assert := assert.New(t)
494mockSeedHost := NewHost(
495mockRawSeedHost.ID, mockRawSeedHost.IP, mockRawSeedHost.Hostname,
496mockRawSeedHost.Port, mockRawSeedHost.DownloadPort, mockRawSeedHost.Type)
497hostManager.Store(mockSeedHost)
498err := hostManager.RunGC()
499assert.NoError(err)
500
501host, loaded := hostManager.Load(mockSeedHost.ID)
502assert.Equal(loaded, true)
503assert.Equal(host.ID, mockSeedHost.ID)
504},
505},
506}
507
508for _, tc := range tests {
509t.Run(tc.name, func(t *testing.T) {
510ctl := gomock.NewController(t)
511defer ctl.Finish()
512gc := gc.NewMockGC(ctl)
513tc.mock(gc.EXPECT())
514
515mockHost := NewHost(
516mockRawHost.ID, mockRawHost.IP, mockRawHost.Hostname,
517mockRawHost.Port, mockRawHost.DownloadPort, mockRawHost.Type)
518mockTask := NewTask(mockTaskID, mockTaskURL, mockTaskTag, mockTaskApplication, commonv2.TaskType_DFDAEMON, mockTaskFilteredQueryParams, mockTaskHeader, mockTaskBackToSourceLimit)
519mockPeer := NewPeer(mockPeerID, mockResourceConfig, mockTask, mockHost)
520hostManager, err := newHostManager(mockHostGCConfig, gc)
521if err != nil {
522t.Fatal(err)
523}
524
525tc.expect(t, hostManager, mockHost, mockPeer)
526})
527}
528}
529