111 lines
3.5 KiB
Go
111 lines
3.5 KiB
Go
package oci
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
)
|
|
|
|
// countingClient 只实现被测方法并计数;其余方法经嵌入 nil 接口(不被调用)。
|
|
type countingClient struct {
|
|
Client
|
|
instCalls int
|
|
adCalls int
|
|
launches int
|
|
}
|
|
|
|
func (f *countingClient) ListInstances(ctx context.Context, cred Credentials, region string) ([]Instance, error) {
|
|
f.instCalls++
|
|
return []Instance{{ID: "i-1", DisplayName: "b"}, {ID: "i-2", DisplayName: "a"}}, nil
|
|
}
|
|
|
|
func (f *countingClient) ListAvailabilityDomains(ctx context.Context, cred Credentials, region string) ([]string, error) {
|
|
f.adCalls++
|
|
return []string{"ad-1"}, nil
|
|
}
|
|
|
|
func (f *countingClient) LaunchInstance(ctx context.Context, cred Credentials, in CreateInstanceInput) (Instance, error) {
|
|
f.launches++
|
|
return Instance{ID: "i-new"}, nil
|
|
}
|
|
|
|
func testCred(tenancy string) Credentials { return Credentials{TenancyOCID: tenancy} }
|
|
|
|
func TestCachedClientHitAndIsolation(t *testing.T) {
|
|
inner := &countingClient{}
|
|
c := NewCachedClient(inner)
|
|
ctx := context.Background()
|
|
|
|
for i := 0; i < 3; i++ {
|
|
if _, err := c.ListInstances(ctx, testCred("t1"), "r1"); err != nil {
|
|
t.Fatalf("ListInstances: %v", err)
|
|
}
|
|
}
|
|
if inner.instCalls != 1 {
|
|
t.Errorf("同 key 三连读回源 %d 次, want 1", inner.instCalls)
|
|
}
|
|
// 不同租户 / 区域各自回源
|
|
_, _ = c.ListInstances(ctx, testCred("t2"), "r1")
|
|
_, _ = c.ListInstances(ctx, testCred("t1"), "r2")
|
|
if inner.instCalls != 3 {
|
|
t.Errorf("跨租户/区域回源 %d 次, want 3", inner.instCalls)
|
|
}
|
|
// 同租户不同 compartment 各自回源,不得共用缓存
|
|
inCompartment := testCred("t1")
|
|
inCompartment.CompartmentID = "ocid1.compartment.a"
|
|
_, _ = c.ListInstances(ctx, inCompartment, "r1")
|
|
if inner.instCalls != 4 {
|
|
t.Errorf("跨 compartment 回源 %d 次, want 4", inner.instCalls)
|
|
}
|
|
}
|
|
|
|
func TestCachedClientWriteBusts(t *testing.T) {
|
|
inner := &countingClient{}
|
|
c := NewCachedClient(inner)
|
|
ctx := context.Background()
|
|
|
|
_, _ = c.ListInstances(ctx, testCred("t1"), "r1")
|
|
_, _ = c.ListAvailabilityDomains(ctx, testCred("t1"), "r1")
|
|
_, _ = c.ListInstances(ctx, testCred("t2"), "r1")
|
|
if _, err := c.LaunchInstance(ctx, testCred("t1"), CreateInstanceInput{}); err != nil {
|
|
t.Fatalf("LaunchInstance: %v", err)
|
|
}
|
|
_, _ = c.ListInstances(ctx, testCred("t1"), "r1")
|
|
_, _ = c.ListAvailabilityDomains(ctx, testCred("t1"), "r1")
|
|
if inner.instCalls != 3 || inner.adCalls != 2 {
|
|
t.Errorf("写后同租户应全部回源: inst=%d want 3, ad=%d want 2", inner.instCalls, inner.adCalls)
|
|
}
|
|
// 其他租户缓存不受影响
|
|
_, _ = c.ListInstances(ctx, testCred("t2"), "r1")
|
|
if inner.instCalls != 3 {
|
|
t.Errorf("t2 缓存被误失效: inst=%d want 3", inner.instCalls)
|
|
}
|
|
}
|
|
|
|
func TestCachedClientReturnsClone(t *testing.T) {
|
|
inner := &countingClient{}
|
|
c := NewCachedClient(inner)
|
|
ctx := context.Background()
|
|
|
|
first, _ := c.ListInstances(ctx, testCred("t1"), "r1")
|
|
first[0], first[1] = first[1], first[0] // 调用方就地重排
|
|
second, _ := c.ListInstances(ctx, testCred("t1"), "r1")
|
|
if second[0].ID != "i-1" {
|
|
t.Errorf("缓存底层数组被调用方污染: second[0]=%s, want i-1", second[0].ID)
|
|
}
|
|
}
|
|
|
|
func TestCachedClientInvalidateTenancy(t *testing.T) {
|
|
inner := &countingClient{}
|
|
c := NewCachedClient(inner)
|
|
ctx := context.Background()
|
|
|
|
_, _ = c.ListInstances(ctx, testCred("t1"), "r1")
|
|
_, _ = c.ListInstances(ctx, testCred("t2"), "r1")
|
|
c.InvalidateTenancy("t1")
|
|
_, _ = c.ListInstances(ctx, testCred("t1"), "r1")
|
|
_, _ = c.ListInstances(ctx, testCred("t2"), "r1")
|
|
if inner.instCalls != 3 {
|
|
t.Fatalf("invalidate tenancy calls = %d, want 3", inner.instCalls)
|
|
}
|
|
}
|