diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2015-07-21 01:29:22 +0200 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2015-07-23 12:43:57 +0200 |
commit | a9c5133a77c8490fad59807f44348214c7f3c954 (patch) | |
tree | ad50140e0da152bc4e3aaec5edbf682e0feff417 /hugolib/pageCache_test.go | |
parent | ea6ae769dc651c2a29e8fb3600fa8c10859f60dc (diff) |
Fix data races in sorting and Reverse
The custom sort functions used from the templates had some subtle data race- and related issues,
especially when used in the single page template.
This commit fixes this by making copies and protect the read and writes with a RWMutex.
The results are cached (it will typically be invoked *number of pages* times with exactly the same data).
This is, not surprisingly, also faster:
```
benchmark old ns/op new ns/op delta
BenchmarkSortByWeightAndReverse 14228 491 -96.55%
benchmark old allocs new allocs delta
BenchmarkSortByWeightAndReverse 1 0 -100.00%
benchmark old bytes new bytes delta
BenchmarkSortByWeightAndReverse 32 0 -100.00%
```
Fixes #1293
Diffstat (limited to 'hugolib/pageCache_test.go')
-rw-r--r-- | hugolib/pageCache_test.go | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/hugolib/pageCache_test.go b/hugolib/pageCache_test.go new file mode 100644 index 000000000..6e48c63cf --- /dev/null +++ b/hugolib/pageCache_test.go @@ -0,0 +1,60 @@ +package hugolib + +import ( + "fmt" + "github.com/stretchr/testify/assert" + "sync" + "sync/atomic" + "testing" +) + +func TestPageCache(t *testing.T) { + c1 := newPageCache() + + changeFirst := func(p Pages) { + p[0].Description = "changed" + } + + var o1 uint64 = 0 + var o2 uint64 = 0 + + var wg sync.WaitGroup + + var l1 sync.Mutex + var l2 sync.Mutex + + var testPageSets []Pages + + for j := 0; j < 50; j++ { + testPageSets = append(testPageSets, createSortTestPages(j+1)) + } + + for i := 0; i < 100; i++ { + wg.Add(1) + go func() { + defer wg.Done() + for j, pages := range testPageSets { + msg := fmt.Sprintf("Go %d %d %d %d", i, j, o1, o2) + l1.Lock() + p, c := c1.get("k1", pages, nil) + assert.Equal(t, !atomic.CompareAndSwapUint64(&o1, uint64(j), uint64(j+1)), c, "c1: "+msg) + l1.Unlock() + p2, c2 := c1.get("k1", p, nil) + assert.True(t, c2) + assert.True(t, probablyEqualPages(p, p2)) + assert.True(t, probablyEqualPages(p, pages)) + assert.NotNil(t, p, msg) + + l2.Lock() + p3, c3 := c1.get("k2", pages, changeFirst) + assert.Equal(t, !atomic.CompareAndSwapUint64(&o2, uint64(j), uint64(j+1)), c3, "c3: "+msg) + l2.Unlock() + assert.NotNil(t, p3, msg) + assert.Equal(t, p3[0].Description, "changed", msg) + } + }() + } + + wg.Wait() + +} |