From 2ca0e8f9a0f9863555a26e984cde15efff9ef8f8 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Fri, 23 Sep 2016 10:17:51 -0400 Subject: Updating golang dependancies (#4075) --- .../golang/groupcache/groupcache_test.go | 447 --------------------- 1 file changed, 447 deletions(-) delete mode 100644 vendor/github.com/golang/groupcache/groupcache_test.go (limited to 'vendor/github.com/golang/groupcache/groupcache_test.go') diff --git a/vendor/github.com/golang/groupcache/groupcache_test.go b/vendor/github.com/golang/groupcache/groupcache_test.go deleted file mode 100644 index 3a4ecc2cc..000000000 --- a/vendor/github.com/golang/groupcache/groupcache_test.go +++ /dev/null @@ -1,447 +0,0 @@ -/* -Copyright 2012 Google Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Tests for groupcache. - -package groupcache - -import ( - "errors" - "fmt" - "hash/crc32" - "math/rand" - "reflect" - "sync" - "testing" - "time" - - "github.com/golang/protobuf/proto" - - pb "github.com/golang/groupcache/groupcachepb" - testpb "github.com/golang/groupcache/testpb" -) - -var ( - once sync.Once - stringGroup, protoGroup Getter - - stringc = make(chan string) - - dummyCtx Context - - // cacheFills is the number of times stringGroup or - // protoGroup's Getter have been called. Read using the - // cacheFills function. - cacheFills AtomicInt -) - -const ( - stringGroupName = "string-group" - protoGroupName = "proto-group" - testMessageType = "google3/net/groupcache/go/test_proto.TestMessage" - fromChan = "from-chan" - cacheSize = 1 << 20 -) - -func testSetup() { - stringGroup = NewGroup(stringGroupName, cacheSize, GetterFunc(func(_ Context, key string, dest Sink) error { - if key == fromChan { - key = <-stringc - } - cacheFills.Add(1) - return dest.SetString("ECHO:" + key) - })) - - protoGroup = NewGroup(protoGroupName, cacheSize, GetterFunc(func(_ Context, key string, dest Sink) error { - if key == fromChan { - key = <-stringc - } - cacheFills.Add(1) - return dest.SetProto(&testpb.TestMessage{ - Name: proto.String("ECHO:" + key), - City: proto.String("SOME-CITY"), - }) - })) -} - -// tests that a Getter's Get method is only called once with two -// outstanding callers. This is the string variant. -func TestGetDupSuppressString(t *testing.T) { - once.Do(testSetup) - // Start two getters. The first should block (waiting reading - // from stringc) and the second should latch on to the first - // one. - resc := make(chan string, 2) - for i := 0; i < 2; i++ { - go func() { - var s string - if err := stringGroup.Get(dummyCtx, fromChan, StringSink(&s)); err != nil { - resc <- "ERROR:" + err.Error() - return - } - resc <- s - }() - } - - // Wait a bit so both goroutines get merged together via - // singleflight. - // TODO(bradfitz): decide whether there are any non-offensive - // debug/test hooks that could be added to singleflight to - // make a sleep here unnecessary. - time.Sleep(250 * time.Millisecond) - - // Unblock the first getter, which should unblock the second - // as well. - stringc <- "foo" - - for i := 0; i < 2; i++ { - select { - case v := <-resc: - if v != "ECHO:foo" { - t.Errorf("got %q; want %q", v, "ECHO:foo") - } - case <-time.After(5 * time.Second): - t.Errorf("timeout waiting on getter #%d of 2", i+1) - } - } -} - -// tests that a Getter's Get method is only called once with two -// outstanding callers. This is the proto variant. -func TestGetDupSuppressProto(t *testing.T) { - once.Do(testSetup) - // Start two getters. The first should block (waiting reading - // from stringc) and the second should latch on to the first - // one. - resc := make(chan *testpb.TestMessage, 2) - for i := 0; i < 2; i++ { - go func() { - tm := new(testpb.TestMessage) - if err := protoGroup.Get(dummyCtx, fromChan, ProtoSink(tm)); err != nil { - tm.Name = proto.String("ERROR:" + err.Error()) - } - resc <- tm - }() - } - - // Wait a bit so both goroutines get merged together via - // singleflight. - // TODO(bradfitz): decide whether there are any non-offensive - // debug/test hooks that could be added to singleflight to - // make a sleep here unnecessary. - time.Sleep(250 * time.Millisecond) - - // Unblock the first getter, which should unblock the second - // as well. - stringc <- "Fluffy" - want := &testpb.TestMessage{ - Name: proto.String("ECHO:Fluffy"), - City: proto.String("SOME-CITY"), - } - for i := 0; i < 2; i++ { - select { - case v := <-resc: - if !reflect.DeepEqual(v, want) { - t.Errorf(" Got: %v\nWant: %v", proto.CompactTextString(v), proto.CompactTextString(want)) - } - case <-time.After(5 * time.Second): - t.Errorf("timeout waiting on getter #%d of 2", i+1) - } - } -} - -func countFills(f func()) int64 { - fills0 := cacheFills.Get() - f() - return cacheFills.Get() - fills0 -} - -func TestCaching(t *testing.T) { - once.Do(testSetup) - fills := countFills(func() { - for i := 0; i < 10; i++ { - var s string - if err := stringGroup.Get(dummyCtx, "TestCaching-key", StringSink(&s)); err != nil { - t.Fatal(err) - } - } - }) - if fills != 1 { - t.Errorf("expected 1 cache fill; got %d", fills) - } -} - -func TestCacheEviction(t *testing.T) { - once.Do(testSetup) - testKey := "TestCacheEviction-key" - getTestKey := func() { - var res string - for i := 0; i < 10; i++ { - if err := stringGroup.Get(dummyCtx, testKey, StringSink(&res)); err != nil { - t.Fatal(err) - } - } - } - fills := countFills(getTestKey) - if fills != 1 { - t.Fatalf("expected 1 cache fill; got %d", fills) - } - - g := stringGroup.(*Group) - evict0 := g.mainCache.nevict - - // Trash the cache with other keys. - var bytesFlooded int64 - // cacheSize/len(testKey) is approximate - for bytesFlooded < cacheSize+1024 { - var res string - key := fmt.Sprintf("dummy-key-%d", bytesFlooded) - stringGroup.Get(dummyCtx, key, StringSink(&res)) - bytesFlooded += int64(len(key) + len(res)) - } - evicts := g.mainCache.nevict - evict0 - if evicts <= 0 { - t.Errorf("evicts = %v; want more than 0", evicts) - } - - // Test that the key is gone. - fills = countFills(getTestKey) - if fills != 1 { - t.Fatalf("expected 1 cache fill after cache trashing; got %d", fills) - } -} - -type fakePeer struct { - hits int - fail bool -} - -func (p *fakePeer) Get(_ Context, in *pb.GetRequest, out *pb.GetResponse) error { - p.hits++ - if p.fail { - return errors.New("simulated error from peer") - } - out.Value = []byte("got:" + in.GetKey()) - return nil -} - -type fakePeers []ProtoGetter - -func (p fakePeers) PickPeer(key string) (peer ProtoGetter, ok bool) { - if len(p) == 0 { - return - } - n := crc32.Checksum([]byte(key), crc32.IEEETable) % uint32(len(p)) - return p[n], p[n] != nil -} - -// tests that peers (virtual, in-process) are hit, and how much. -func TestPeers(t *testing.T) { - once.Do(testSetup) - rand.Seed(123) - peer0 := &fakePeer{} - peer1 := &fakePeer{} - peer2 := &fakePeer{} - peerList := fakePeers([]ProtoGetter{peer0, peer1, peer2, nil}) - const cacheSize = 0 // disabled - localHits := 0 - getter := func(_ Context, key string, dest Sink) error { - localHits++ - return dest.SetString("got:" + key) - } - testGroup := newGroup("TestPeers-group", cacheSize, GetterFunc(getter), peerList) - run := func(name string, n int, wantSummary string) { - // Reset counters - localHits = 0 - for _, p := range []*fakePeer{peer0, peer1, peer2} { - p.hits = 0 - } - - for i := 0; i < n; i++ { - key := fmt.Sprintf("key-%d", i) - want := "got:" + key - var got string - err := testGroup.Get(dummyCtx, key, StringSink(&got)) - if err != nil { - t.Errorf("%s: error on key %q: %v", name, key, err) - continue - } - if got != want { - t.Errorf("%s: for key %q, got %q; want %q", name, key, got, want) - } - } - summary := func() string { - return fmt.Sprintf("localHits = %d, peers = %d %d %d", localHits, peer0.hits, peer1.hits, peer2.hits) - } - if got := summary(); got != wantSummary { - t.Errorf("%s: got %q; want %q", name, got, wantSummary) - } - } - resetCacheSize := func(maxBytes int64) { - g := testGroup - g.cacheBytes = maxBytes - g.mainCache = cache{} - g.hotCache = cache{} - } - - // Base case; peers all up, with no problems. - resetCacheSize(1 << 20) - run("base", 200, "localHits = 49, peers = 51 49 51") - - // Verify cache was hit. All localHits are gone, and some of - // the peer hits (the ones randomly selected to be maybe hot) - run("cached_base", 200, "localHits = 0, peers = 49 47 48") - resetCacheSize(0) - - // With one of the peers being down. - // TODO(bradfitz): on a peer number being unavailable, the - // consistent hashing should maybe keep trying others to - // spread the load out. Currently it fails back to local - // execution if the first consistent-hash slot is unavailable. - peerList[0] = nil - run("one_peer_down", 200, "localHits = 100, peers = 0 49 51") - - // Failing peer - peerList[0] = peer0 - peer0.fail = true - run("peer0_failing", 200, "localHits = 100, peers = 51 49 51") -} - -func TestTruncatingByteSliceTarget(t *testing.T) { - var buf [100]byte - s := buf[:] - if err := stringGroup.Get(dummyCtx, "short", TruncatingByteSliceSink(&s)); err != nil { - t.Fatal(err) - } - if want := "ECHO:short"; string(s) != want { - t.Errorf("short key got %q; want %q", s, want) - } - - s = buf[:6] - if err := stringGroup.Get(dummyCtx, "truncated", TruncatingByteSliceSink(&s)); err != nil { - t.Fatal(err) - } - if want := "ECHO:t"; string(s) != want { - t.Errorf("truncated key got %q; want %q", s, want) - } -} - -func TestAllocatingByteSliceTarget(t *testing.T) { - var dst []byte - sink := AllocatingByteSliceSink(&dst) - - inBytes := []byte("some bytes") - sink.SetBytes(inBytes) - if want := "some bytes"; string(dst) != want { - t.Errorf("SetBytes resulted in %q; want %q", dst, want) - } - v, err := sink.view() - if err != nil { - t.Fatalf("view after SetBytes failed: %v", err) - } - if &inBytes[0] == &dst[0] { - t.Error("inBytes and dst share memory") - } - if &inBytes[0] == &v.b[0] { - t.Error("inBytes and view share memory") - } - if &dst[0] == &v.b[0] { - t.Error("dst and view share memory") - } -} - -// orderedFlightGroup allows the caller to force the schedule of when -// orig.Do will be called. This is useful to serialize calls such -// that singleflight cannot dedup them. -type orderedFlightGroup struct { - mu sync.Mutex - stage1 chan bool - stage2 chan bool - orig flightGroup -} - -func (g *orderedFlightGroup) Do(key string, fn func() (interface{}, error)) (interface{}, error) { - <-g.stage1 - <-g.stage2 - g.mu.Lock() - defer g.mu.Unlock() - return g.orig.Do(key, fn) -} - -// TestNoDedup tests invariants on the cache size when singleflight is -// unable to dedup calls. -func TestNoDedup(t *testing.T) { - const testkey = "testkey" - const testval = "testval" - g := newGroup("testgroup", 1024, GetterFunc(func(_ Context, key string, dest Sink) error { - return dest.SetString(testval) - }), nil) - - orderedGroup := &orderedFlightGroup{ - stage1: make(chan bool), - stage2: make(chan bool), - orig: g.loadGroup, - } - // Replace loadGroup with our wrapper so we can control when - // loadGroup.Do is entered for each concurrent request. - g.loadGroup = orderedGroup - - // Issue two idential requests concurrently. Since the cache is - // empty, it will miss. Both will enter load(), but we will only - // allow one at a time to enter singleflight.Do, so the callback - // function will be called twice. - resc := make(chan string, 2) - for i := 0; i < 2; i++ { - go func() { - var s string - if err := g.Get(dummyCtx, testkey, StringSink(&s)); err != nil { - resc <- "ERROR:" + err.Error() - return - } - resc <- s - }() - } - - // Ensure both goroutines have entered the Do routine. This implies - // both concurrent requests have checked the cache, found it empty, - // and called load(). - orderedGroup.stage1 <- true - orderedGroup.stage1 <- true - orderedGroup.stage2 <- true - orderedGroup.stage2 <- true - - for i := 0; i < 2; i++ { - if s := <-resc; s != testval { - t.Errorf("result is %s want %s", s, testval) - } - } - - const wantItems = 1 - if g.mainCache.items() != wantItems { - t.Errorf("mainCache has %d items, want %d", g.mainCache.items(), wantItems) - } - - // If the singleflight callback doesn't double-check the cache again - // upon entry, we would increment nbytes twice but the entry would - // only be in the cache once. - const wantBytes = int64(len(testkey) + len(testval)) - if g.mainCache.nbytes != wantBytes { - t.Errorf("cache has %d bytes, want %d", g.mainCache.nbytes, wantBytes) - } -} - -// TODO(bradfitz): port the Google-internal full integration test into here, -// using HTTP requests instead of our RPC system. -- cgit v1.2.3-1-g7c22