github.com/tiagovtristao/plz@v13.4.0+incompatible/src/cache/async_cache_test.go (about)

     1  package cache
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  
    11  	"github.com/thought-machine/please/src/core"
    12  )
    13  
    14  func TestStore(t *testing.T) {
    15  	mCache, aCache := makeCaches()
    16  	target := makeTarget("//pkg1:test_store")
    17  	aCache.Store(target, nil)
    18  	aCache.Shutdown()
    19  	assert.False(t, mCache.inFlight[target])
    20  	assert.True(t, mCache.completed[target])
    21  }
    22  
    23  func TestStoreExtra(t *testing.T) {
    24  	mCache, aCache := makeCaches()
    25  	target := makeTarget("//pkg1:test_store_extra")
    26  	aCache.StoreExtra(target, nil, "some_other_file")
    27  	aCache.Shutdown()
    28  	assert.False(t, mCache.inFlight[target])
    29  	assert.True(t, mCache.completed[target])
    30  }
    31  
    32  func TestRetrieve(t *testing.T) {
    33  	mCache, aCache := makeCaches()
    34  	target := makeTarget("//pkg1:test_retrieve")
    35  	aCache.Retrieve(target, nil)
    36  	aCache.Shutdown()
    37  	assert.False(t, mCache.inFlight[target])
    38  	assert.True(t, mCache.completed[target])
    39  }
    40  
    41  func TestRetrieveExtra(t *testing.T) {
    42  	mCache, aCache := makeCaches()
    43  	target := makeTarget("//pkg1:test_retrieve_extra")
    44  	aCache.RetrieveExtra(target, nil, "some_other_file")
    45  	aCache.Shutdown()
    46  	assert.False(t, mCache.inFlight[target])
    47  	assert.True(t, mCache.completed[target])
    48  }
    49  
    50  func TestClean(t *testing.T) {
    51  	mCache, aCache := makeCaches()
    52  	target := makeTarget("//pkg1:test_clean")
    53  	aCache.Clean(target)
    54  	aCache.Shutdown()
    55  	assert.False(t, mCache.inFlight[target])
    56  	assert.True(t, mCache.completed[target])
    57  }
    58  
    59  func TestSimulateBuild(t *testing.T) {
    60  	// Attempt to simulate what a normal build would do and confirm that the actions come
    61  	// back out in the correct order.
    62  	// This is a little obsolete now, it was ultimately solved by adding extra arguments to Store
    63  	// instead of requiring extra calls to StoreExtra, but that means there isn't that much
    64  	// left to exercise in this test any more.
    65  	const n = 100
    66  	var wg sync.WaitGroup
    67  	wg.Add(n)
    68  	mCache, aCache := makeCaches()
    69  	for i := 0; i < n; i++ {
    70  		go func(i int) {
    71  			target := makeTarget(fmt.Sprintf("//test_pkg:target%03d", i))
    72  			aCache.Store(target, nil, fmt.Sprintf("file%03d", i), fmt.Sprintf("file%03d_2", i))
    73  			wg.Done()
    74  		}(i)
    75  	}
    76  	wg.Wait()
    77  	aCache.Shutdown()
    78  	assert.Equal(t, n, len(mCache.stored))
    79  	for target, stored := range mCache.stored {
    80  		assert.Equal(t, []string{
    81  			"",
    82  			"file" + target.Label.Name[len(target.Label.Name)-3:],
    83  			"file" + target.Label.Name[len(target.Label.Name)-3:] + "_2",
    84  		}, stored)
    85  	}
    86  }
    87  
    88  // Fake cache implementation to ensure our async cache behaves itself.
    89  type mockCache struct {
    90  	sync.Mutex
    91  	inFlight  map[*core.BuildTarget]bool
    92  	completed map[*core.BuildTarget]bool
    93  	stored    map[*core.BuildTarget][]string
    94  }
    95  
    96  func (c *mockCache) Store(target *core.BuildTarget, key []byte, files ...string) {
    97  	c.Lock()
    98  	if c.inFlight[target] {
    99  		panic("Concurrent store on " + target.Label.String())
   100  	}
   101  	c.inFlight[target] = true
   102  	c.Unlock()
   103  	time.Sleep(10 * time.Millisecond) // Fake a small delay to mimic the real thing
   104  	c.Lock()
   105  	c.inFlight[target] = false
   106  	c.completed[target] = true
   107  	c.stored[target] = append(c.stored[target], "")
   108  	c.stored[target] = append(c.stored[target], files...)
   109  	c.Unlock()
   110  }
   111  
   112  func (c *mockCache) StoreExtra(target *core.BuildTarget, key []byte, file string) {
   113  	c.Store(target, key, file)
   114  }
   115  
   116  func (c *mockCache) Retrieve(target *core.BuildTarget, key []byte) bool {
   117  	c.Lock()
   118  	c.completed[target] = true
   119  	c.Unlock()
   120  	return false
   121  }
   122  
   123  func (c *mockCache) RetrieveExtra(target *core.BuildTarget, key []byte, file string) bool {
   124  	return c.Retrieve(target, key)
   125  }
   126  
   127  func (c *mockCache) Clean(target *core.BuildTarget) {
   128  	c.Retrieve(target, nil)
   129  }
   130  
   131  func (c *mockCache) CleanAll() {}
   132  
   133  func (*mockCache) Shutdown() {}
   134  
   135  func makeTarget(label string) *core.BuildTarget {
   136  	return core.NewBuildTarget(core.ParseBuildLabel(label, ""))
   137  }
   138  
   139  func makeCaches() (*mockCache, core.Cache) {
   140  	mCache := &mockCache{
   141  		inFlight:  make(map[*core.BuildTarget]bool),
   142  		completed: make(map[*core.BuildTarget]bool),
   143  		stored:    make(map[*core.BuildTarget][]string),
   144  	}
   145  	config := core.DefaultConfiguration()
   146  	config.Cache.Workers = 10
   147  	return mCache, newAsyncCache(mCache, config)
   148  }