github.com/slspeek/camlistore_namedsearch@v0.0.0-20140519202248-ed6f70f7721a/pkg/gc/gc_test.go (about)

     1  /*
     2  Copyright 2014 The Camlistore 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  	"reflect"
    21  	"sort"
    22  	"testing"
    23  
    24  	"camlistore.org/pkg/context"
    25  )
    26  
    27  func sl(v ...string) []string {
    28  	if len(v) == 0 {
    29  		return nil
    30  	}
    31  	return v
    32  }
    33  
    34  var collectTests = []struct {
    35  	name      string
    36  	world     []string
    37  	roots     []string
    38  	graph     map[string][]string
    39  	wantWorld []string
    40  }{
    41  	{
    42  		name:      "delete everything",
    43  		world:     sl("a", "b", "c"),
    44  		wantWorld: sl(),
    45  	},
    46  
    47  	{
    48  		name:      "keep everything",
    49  		world:     sl("a", "b", "c"),
    50  		roots:     sl("a", "b", "c"),
    51  		wantWorld: sl("a", "b", "c"),
    52  	},
    53  
    54  	{
    55  		name:  "keep all via chain",
    56  		world: sl("a", "b", "c", "d", "e"),
    57  		roots: sl("a"),
    58  		graph: map[string][]string{
    59  			"a": sl("b"),
    60  			"b": sl("c"),
    61  			"c": sl("d"),
    62  			"d": sl("e"),
    63  		},
    64  		wantWorld: sl("a", "b", "c", "d", "e"),
    65  	},
    66  
    67  	{
    68  		name:  "keep all via fan",
    69  		world: sl("a", "b", "c", "d", "e"),
    70  		roots: sl("a"),
    71  		graph: map[string][]string{
    72  			"a": sl("b", "c", "d", "e"),
    73  		},
    74  		wantWorld: sl("a", "b", "c", "d", "e"),
    75  	},
    76  
    77  	{
    78  		name:  "c dies, two roots",
    79  		world: sl("a", "b", "c", "d", "e"),
    80  		roots: sl("a", "d"),
    81  		graph: map[string][]string{
    82  			"a": sl("b"),
    83  			"d": sl("e"),
    84  		},
    85  		wantWorld: sl("a", "b", "d", "e"),
    86  	},
    87  }
    88  
    89  type worldSet map[string]bool
    90  
    91  func newWorldSet(start []string) worldSet {
    92  	s := make(worldSet)
    93  	for _, v := range start {
    94  		s[v] = true
    95  	}
    96  	return s
    97  }
    98  
    99  func (s worldSet) Delete(it Item) error {
   100  	delete(s, it.(string))
   101  	return nil
   102  }
   103  
   104  func (s worldSet) items() []string {
   105  	if len(s) == 0 {
   106  		return nil
   107  	}
   108  	ret := make([]string, 0, len(s))
   109  	for it := range s {
   110  		ret = append(ret, it)
   111  	}
   112  	sort.Strings(ret)
   113  	return ret
   114  }
   115  
   116  func TestCollector(t *testing.T) {
   117  	for _, tt := range collectTests {
   118  		if tt.name == "" {
   119  			panic("no name in test")
   120  		}
   121  		w := newWorldSet(tt.world)
   122  		c := &Collector{
   123  			World:          testWorld{},
   124  			Marker:         testMarker(map[Item]bool{}),
   125  			Roots:          testEnum(tt.roots),
   126  			Sweeper:        testEnum(tt.world),
   127  			ItemEnumerator: testItemEnum(tt.graph),
   128  			Deleter:        w,
   129  		}
   130  		if err := c.Collect(context.New()); err != nil {
   131  			t.Errorf("%s: Collect = %v", tt.name, err)
   132  		}
   133  		got := w.items()
   134  		if !reflect.DeepEqual(tt.wantWorld, got) {
   135  			t.Errorf("%s: world = %q; want %q", tt.name, got, tt.wantWorld)
   136  		}
   137  	}
   138  }
   139  
   140  type testEnum []string
   141  
   142  func (s testEnum) Enumerate(ctx *context.Context, dest chan<- Item) error {
   143  	defer close(dest)
   144  	for _, v := range s {
   145  		select {
   146  		case dest <- v:
   147  		case <-ctx.Done():
   148  			return context.ErrCanceled
   149  		}
   150  	}
   151  	return nil
   152  }
   153  
   154  type testItemEnum map[string][]string
   155  
   156  func (m testItemEnum) EnumerateItem(ctx *context.Context, it Item, dest chan<- Item) error {
   157  	defer close(dest)
   158  	for _, v := range m[it.(string)] {
   159  		select {
   160  		case dest <- v:
   161  		case <-ctx.Done():
   162  			return context.ErrCanceled
   163  		}
   164  	}
   165  	return nil
   166  }
   167  
   168  type testMarker map[Item]bool
   169  
   170  func (m testMarker) Mark(it Item) error {
   171  	m[it] = true
   172  	return nil
   173  }
   174  
   175  func (m testMarker) IsMarked(it Item) (v bool, err error) {
   176  	v = m[it]
   177  	return
   178  }
   179  
   180  type testWorld struct{}
   181  
   182  func (testWorld) Start() error { return nil }
   183  func (testWorld) Stop() error  { return nil }