github.com/containerd/containerd@v22.0.0-20200918172823-438c87b8e050+incompatible/gc/gc_test.go (about) 1 /* 2 Copyright The containerd 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 17 package gc 18 19 import ( 20 "context" 21 "reflect" 22 "testing" 23 ) 24 25 func TestTricolorBasic(t *testing.T) { 26 roots := []string{"A", "C"} 27 all := []string{"A", "B", "C", "D", "E", "F", "G", "H"} 28 refs := map[string][]string{ 29 "A": {"B"}, 30 "B": {"A"}, 31 "C": {"D", "F", "B"}, 32 "E": {"F", "G"}, 33 "F": {"H"}, 34 } 35 36 expected := toNodes([]string{"A", "B", "C", "D", "F", "H"}) 37 38 reachable, err := Tricolor(toNodes(roots), lookup(refs)) 39 if err != nil { 40 t.Fatal(err) 41 } 42 43 var sweeped []Node 44 for _, a := range toNodes(all) { 45 if _, ok := reachable[a]; ok { 46 sweeped = append(sweeped, a) 47 } 48 } 49 50 if !reflect.DeepEqual(sweeped, expected) { 51 t.Fatalf("incorrect unreachable set: %v != %v", sweeped, expected) 52 } 53 } 54 55 func TestConcurrentBasic(t *testing.T) { 56 roots := []string{"A", "C"} 57 all := []string{"A", "B", "C", "D", "E", "F", "G", "H", "I"} 58 refs := map[string][]string{ 59 "A": {"B"}, 60 "B": {"A"}, 61 "C": {"D", "F", "B"}, 62 "E": {"F", "G"}, 63 "F": {"H"}, 64 "G": {"I"}, 65 } 66 67 expected := toNodes([]string{"A", "B", "C", "D", "F", "H"}) 68 69 ctx := context.Background() 70 rootC := make(chan Node) 71 go func() { 72 writeNodes(ctx, rootC, toNodes(roots)) 73 close(rootC) 74 }() 75 76 reachable, err := ConcurrentMark(ctx, rootC, lookupc(refs)) 77 if err != nil { 78 t.Fatal(err) 79 } 80 81 var sweeped []Node 82 for _, a := range toNodes(all) { 83 if _, ok := reachable[a]; ok { 84 sweeped = append(sweeped, a) 85 } 86 } 87 88 if !reflect.DeepEqual(sweeped, expected) { 89 t.Fatalf("incorrect unreachable set: %v != %v", sweeped, expected) 90 } 91 } 92 93 func writeNodes(ctx context.Context, nc chan<- Node, nodes []Node) { 94 for _, n := range nodes { 95 select { 96 case nc <- n: 97 case <-ctx.Done(): 98 return 99 } 100 } 101 } 102 103 func lookup(refs map[string][]string) func(id Node) ([]Node, error) { 104 return func(ref Node) ([]Node, error) { 105 return toNodes(refs[ref.Key]), nil 106 } 107 } 108 109 func lookupc(refs map[string][]string) func(context.Context, Node, func(Node)) error { 110 return func(ctx context.Context, ref Node, fn func(Node)) error { 111 for _, n := range toNodes(refs[ref.Key]) { 112 fn(n) 113 } 114 return nil 115 } 116 } 117 118 func toNodes(s []string) []Node { 119 n := make([]Node, len(s)) 120 for i := range s { 121 n[i] = Node{ 122 Key: s[i], 123 } 124 } 125 return n 126 }