github.com/npaton/distribution@v2.3.1-rc.0+incompatible/registry/proxy/scheduler/scheduler_test.go (about)

     1  package scheduler
     2  
     3  import (
     4  	"encoding/json"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/docker/distribution/context"
     9  	"github.com/docker/distribution/reference"
    10  	"github.com/docker/distribution/registry/storage/driver/inmemory"
    11  )
    12  
    13  func testRefs(t *testing.T) (reference.Reference, reference.Reference, reference.Reference) {
    14  	ref1, err := reference.Parse("testrepo@sha256:aaaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
    15  	if err != nil {
    16  		t.Fatalf("could not parse reference: %v", err)
    17  	}
    18  
    19  	ref2, err := reference.Parse("testrepo@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")
    20  	if err != nil {
    21  		t.Fatalf("could not parse reference: %v", err)
    22  	}
    23  
    24  	ref3, err := reference.Parse("testrepo@sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc")
    25  	if err != nil {
    26  		t.Fatalf("could not parse reference: %v", err)
    27  	}
    28  
    29  	return ref1, ref2, ref3
    30  }
    31  
    32  func TestSchedule(t *testing.T) {
    33  	ref1, ref2, ref3 := testRefs(t)
    34  	timeUnit := time.Millisecond
    35  	remainingRepos := map[string]bool{
    36  		ref1.String(): true,
    37  		ref2.String(): true,
    38  		ref3.String(): true,
    39  	}
    40  
    41  	s := New(context.Background(), inmemory.New(), "/ttl")
    42  	deleteFunc := func(repoName reference.Reference) error {
    43  		if len(remainingRepos) == 0 {
    44  			t.Fatalf("Incorrect expiry count")
    45  		}
    46  		_, ok := remainingRepos[repoName.String()]
    47  		if !ok {
    48  			t.Fatalf("Trying to remove nonexistant repo: %s", repoName)
    49  		}
    50  		t.Log("removing", repoName)
    51  		delete(remainingRepos, repoName.String())
    52  
    53  		return nil
    54  	}
    55  	s.onBlobExpire = deleteFunc
    56  	err := s.Start()
    57  	if err != nil {
    58  		t.Fatalf("Error starting ttlExpirationScheduler: %s", err)
    59  	}
    60  
    61  	s.add(ref1, 3*timeUnit, entryTypeBlob)
    62  	s.add(ref2, 1*timeUnit, entryTypeBlob)
    63  
    64  	func() {
    65  		s.add(ref3, 1*timeUnit, entryTypeBlob)
    66  
    67  	}()
    68  
    69  	// Ensure all repos are deleted
    70  	<-time.After(50 * timeUnit)
    71  	if len(remainingRepos) != 0 {
    72  		t.Fatalf("Repositories remaining: %#v", remainingRepos)
    73  	}
    74  }
    75  
    76  func TestRestoreOld(t *testing.T) {
    77  	ref1, ref2, _ := testRefs(t)
    78  	remainingRepos := map[string]bool{
    79  		ref1.String(): true,
    80  		ref2.String(): true,
    81  	}
    82  
    83  	deleteFunc := func(r reference.Reference) error {
    84  		if r.String() == ref1.String() && len(remainingRepos) == 2 {
    85  			t.Errorf("ref1 should be removed first")
    86  		}
    87  		_, ok := remainingRepos[r.String()]
    88  		if !ok {
    89  			t.Fatalf("Trying to remove nonexistant repo: %s", r)
    90  		}
    91  		delete(remainingRepos, r.String())
    92  		return nil
    93  	}
    94  
    95  	timeUnit := time.Millisecond
    96  	serialized, err := json.Marshal(&map[string]schedulerEntry{
    97  		ref1.String(): {
    98  			Expiry:    time.Now().Add(1 * timeUnit),
    99  			Key:       ref1.String(),
   100  			EntryType: 0,
   101  		},
   102  		ref2.String(): {
   103  			Expiry:    time.Now().Add(-3 * timeUnit), // TTL passed, should be removed first
   104  			Key:       ref2.String(),
   105  			EntryType: 0,
   106  		},
   107  	})
   108  	if err != nil {
   109  		t.Fatalf("Error serializing test data: %s", err.Error())
   110  	}
   111  
   112  	ctx := context.Background()
   113  	pathToStatFile := "/ttl"
   114  	fs := inmemory.New()
   115  	err = fs.PutContent(ctx, pathToStatFile, serialized)
   116  	if err != nil {
   117  		t.Fatal("Unable to write serialized data to fs")
   118  	}
   119  	s := New(context.Background(), fs, "/ttl")
   120  	s.onBlobExpire = deleteFunc
   121  	err = s.Start()
   122  	if err != nil {
   123  		t.Fatalf("Error starting ttlExpirationScheduler: %s", err)
   124  	}
   125  
   126  	<-time.After(50 * timeUnit)
   127  	if len(remainingRepos) != 0 {
   128  		t.Fatalf("Repositories remaining: %#v", remainingRepos)
   129  	}
   130  }
   131  
   132  func TestStopRestore(t *testing.T) {
   133  	ref1, ref2, _ := testRefs(t)
   134  
   135  	timeUnit := time.Millisecond
   136  	remainingRepos := map[string]bool{
   137  		ref1.String(): true,
   138  		ref2.String(): true,
   139  	}
   140  
   141  	deleteFunc := func(r reference.Reference) error {
   142  		delete(remainingRepos, r.String())
   143  		return nil
   144  	}
   145  
   146  	fs := inmemory.New()
   147  	pathToStateFile := "/ttl"
   148  	s := New(context.Background(), fs, pathToStateFile)
   149  	s.onBlobExpire = deleteFunc
   150  
   151  	err := s.Start()
   152  	if err != nil {
   153  		t.Fatalf(err.Error())
   154  	}
   155  	s.add(ref1, 300*timeUnit, entryTypeBlob)
   156  	s.add(ref2, 100*timeUnit, entryTypeBlob)
   157  
   158  	// Start and stop before all operations complete
   159  	// state will be written to fs
   160  	s.Stop()
   161  	time.Sleep(10 * time.Millisecond)
   162  
   163  	// v2 will restore state from fs
   164  	s2 := New(context.Background(), fs, pathToStateFile)
   165  	s2.onBlobExpire = deleteFunc
   166  	err = s2.Start()
   167  	if err != nil {
   168  		t.Fatalf("Error starting v2: %s", err.Error())
   169  	}
   170  
   171  	<-time.After(500 * timeUnit)
   172  	if len(remainingRepos) != 0 {
   173  		t.Fatalf("Repositories remaining: %#v", remainingRepos)
   174  	}
   175  
   176  }
   177  
   178  func TestDoubleStart(t *testing.T) {
   179  	s := New(context.Background(), inmemory.New(), "/ttl")
   180  	err := s.Start()
   181  	if err != nil {
   182  		t.Fatalf("Unable to start scheduler")
   183  	}
   184  	err = s.Start()
   185  	if err == nil {
   186  		t.Fatalf("Scheduler started twice without error")
   187  	}
   188  }