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  }