Repository: etcd-io/etcd
File: tests/integration/cache_test.go (Go)

Code before:
		initialLoadRevision int64
	}{
		{"empty cache", 0},
		{"partial load", 4},
		{"complete load", lastRev},
	}

	for _, tc := range tcs {
		tc := tc
		t.Run(tc.name, func(t *testing.T) {
			integration.BeforeTest(t)
			clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1})
			t.Cleanup(func() { clus.Terminate(t) })
			client := clus.Client(0)
			kv := client.KV
			ctx := t.Context()

			t.Log("Classify and load first batch of events")
			var firstBatch, secondBatch []*clientv3.Event
			for _, ev := range TestGetEvents {
				if ev.Kv.ModRevision <= tc.initialLoadRevision {
					firstBatch = append(firstBatch, ev)
				} else {
					secondBatch = append(secondBatch, ev)
				}
			}
			applyEvents(ctx, t, kv, firstBatch)

			t.Log("Start cache")
			c, err := cache.New(client, "")
			if err != nil {
				t.Fatalf("cache.New: %v", err)
			}
			defer c.Close()
			if err := c.WaitReady(ctx); err != nil {
				t.Fatal(err)
			}
			if tc.initialLoadRevision > 0 {
				if err := c.WaitForRevision(ctx, tc.initialLoadRevision); err != nil {
					t.Fatalf("cache never caught up to rev %d: %v", tc.initialLoadRevision, err)
				}
			}

			t.Log("Load second batch of events")
			lastRev := applyEvents(ctx, t, kv, secondBatch)
			if err := c.WaitForRevision(ctx, lastRev); err != nil {
				t.Fatalf("cache never caught up to rev %d: %v", lastRev, err)
			}

			t.Log("Validate")
			for _, tc := range getTestCases {

Review comment (performance):
Maybe instead of doing filtering here do it in test cases

```
tcs := []struct {
		name                string
		initialEvents, followupEvents []*clientv3.Event
	}{
		{"empty cache", nil, TestGetEvents},
		{"partial load", filterEvents(TestGetEvents, revisionLessThan(4)), filterEvents(TestGetEvents, revisionGreatherEqual(4))},
		{"complete load", TestGetEvents, nil},
	}
```

Code after:
		{"empty cache", nil, TestGetEvents},
		{"partial load", filterEvents(TestGetEvents, revLessThan(4)), filterEvents(TestGetEvents, revGreaterEqual(4))},
		{"complete load", TestGetEvents, nil},
	}

	for _, tc := range tcs {
		t.Run(tc.name, func(t *testing.T) {
			integration.BeforeTest(t)
			clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1})
			t.Cleanup(func() { clus.Terminate(t) })
			client, kv := clus.Client(0), clus.Client(0).KV

			testGet(t, kv, func() Getter {
				c, err := cache.New(client, "")
				if err != nil {
					t.Fatalf("cache.New: %v", err)
				}
				t.Cleanup(c.Close)
				if err := c.WaitReady(t.Context()); err != nil {
					t.Fatalf("cache not ready: %v", err)
				}
				return c
			}, tc.initialEvents, tc.followupEvents)
		})
	}
}

func TestGet(t *testing.T) {
	integration.BeforeTest(t)
	clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1})
	t.Cleanup(func() { clus.Terminate(t) })

	client := clus.Client(0)
	kv := client.KV

	testGet(t, kv, func() Getter { return kv }, TestGetEvents, nil)
}

func testGet(t *testing.T, kv clientv3.KV, getReader func() Getter, initialEvents, followupEvents []*clientv3.Event) {
	ctx := t.Context()
	t.Log("Setup")
	lastRev := applyEvents(ctx, t, kv, initialEvents)

	reader := getReader()
	if c, ok := reader.(*cache.Cache); ok {
		if err := c.WaitForRevision(ctx, lastRev); err != nil {
			t.Fatalf("cache never caught up to rev %d: %v", lastRev, err)
		}
	}

	lastRev = applyEvents(ctx, t, kv, followupEvents)