Skip to content

Commit efcfa74

Browse files
author
Harvey Lowndes
committed
Added tests for request rate limiting
1 parent 19cfbf1 commit efcfa74

File tree

3 files changed

+152
-6
lines changed

3 files changed

+152
-6
lines changed

pkg/oci/ccm.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ import (
4545
)
4646

4747
const (
48-
RateLimitQPSDefault = 1.0
49-
RateLimitBucketDefault = 5
48+
rateLimitQPSDefault = 1.0
49+
rateLimitBucketDefault = 5
5050
)
5151

5252
// ProviderName uniquely identifies the Oracle Bare Metal Cloud Services (OCI)
@@ -232,16 +232,16 @@ func buildConfigurationProvider(config *Config) (common.ConfigurationProvider, e
232232
func buildNewRateLimiter(config *RateLimiterConfig) client.RateLimiter {
233233
// Set to default values if configuration not declared
234234
if config.RateLimitQPSRead == 0 {
235-
config.RateLimitQPSRead = RateLimitQPSDefault
235+
config.RateLimitQPSRead = rateLimitQPSDefault
236236
}
237237
if config.RateLimitBucketRead == 0 {
238-
config.RateLimitBucketRead = RateLimitBucketDefault
238+
config.RateLimitBucketRead = rateLimitBucketDefault
239239
}
240240
if config.RateLimitQPSWrite == 0 {
241-
config.RateLimitQPSWrite = RateLimitQPSDefault
241+
config.RateLimitQPSWrite = rateLimitQPSDefault
242242
}
243243
if config.RateLimitBucketWrite == 0 {
244-
config.RateLimitBucketWrite = RateLimitBucketDefault
244+
config.RateLimitBucketWrite = rateLimitBucketDefault
245245
}
246246

247247
rateLimiter := client.RateLimiter{

pkg/oci/ccm_test.go

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright 2017 Oracle and/or its affiliates. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package oci
16+
17+
import (
18+
"testing"
19+
)
20+
21+
func TestBuildRateLimiterWithConfig(t *testing.T) {
22+
var qpsRead float32 = 6.0
23+
bucketRead := 20
24+
var qpsWrite float32 = 8.0
25+
bucketWrite := 20
26+
27+
rateLimiterConfig := &RateLimiterConfig{
28+
RateLimitQPSRead: qpsRead,
29+
RateLimitBucketRead: bucketRead,
30+
RateLimitQPSWrite: qpsWrite,
31+
RateLimitBucketWrite: bucketWrite,
32+
}
33+
34+
rateLimiter := buildNewRateLimiter(rateLimiterConfig)
35+
36+
if rateLimiter.Reader.QPS() != qpsRead {
37+
t.Errorf("unexpected QPS (read) value: expected %f but found %f", qpsRead, rateLimiter.Reader.QPS())
38+
}
39+
40+
if rateLimiter.Writer.QPS() != qpsWrite {
41+
t.Errorf("unexpected QPS (write) value: expected %f but found %f", qpsWrite, rateLimiter.Writer.QPS())
42+
}
43+
}
44+
45+
func TestBuildRateLimiterWithDefaults(t *testing.T) {
46+
rateLimiterConfig := &RateLimiterConfig{}
47+
48+
rateLimiter := buildNewRateLimiter(rateLimiterConfig)
49+
50+
if rateLimiter.Reader.QPS() != RateLimitQPSDefault {
51+
t.Errorf("unexpected QPS (read) value: expected %f but found %f", RateLimitQPSDefault, rateLimiter.Reader.QPS())
52+
}
53+
54+
if rateLimiter.Writer.QPS() != RateLimitQPSDefault {
55+
t.Errorf("unexpected QPS (write) value: expected %f but found %f", RateLimitQPSDefault, rateLimiter.Writer.QPS())
56+
}
57+
}

pkg/oci/client/client_test.go

+89
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515
package client
1616

1717
import (
18+
"context"
1819
"testing"
1920

2021
"github.com/oracle/oci-go-sdk/core"
22+
"k8s.io/client-go/util/flowcontrol"
2123
)
2224

2325
func TestInstanceTerminalState(t *testing.T) {
@@ -54,3 +56,90 @@ func TestInstanceTerminalState(t *testing.T) {
5456
})
5557
}
5658
}
59+
60+
type mockComputeClient struct{}
61+
62+
type mockVirtualNetworkClient struct{}
63+
64+
type mockLoadBalancerClient struct{}
65+
66+
func TestRateLimiting(t *testing.T) {
67+
var qpsRead float32 = 5
68+
bucketRead := 5
69+
var qpsWrite float32 = 10
70+
bucketWrite := 5
71+
72+
rateLimiter := RateLimiter{
73+
Reader: flowcontrol.NewTokenBucketRateLimiter(
74+
qpsRead,
75+
bucketRead),
76+
Writer: flowcontrol.NewTokenBucketRateLimiter(
77+
qpsWrite,
78+
bucketWrite),
79+
}
80+
81+
client := newClient(rateLimiter)
82+
83+
// Read requests up to qpsRead should pass and the others fail
84+
for i := 0; i < int(qpsRead)*2; i++ {
85+
_, err := client.Compute().GetInstance(context.Background(), "123345")
86+
p := (err == nil)
87+
88+
if (i < int(qpsRead) && !p) || (i >= int(qpsRead) && p) {
89+
t.Errorf("unexpected result from request %d: %v", i, err)
90+
}
91+
}
92+
93+
// Write requests up to qpsWrite should pass and the others fail
94+
ids := [2]string{"12334"}
95+
for i := 0; i < int(qpsWrite)*2; i++ {
96+
req := core.UpdateSecurityListRequest{
97+
SecurityListId: &ids[0],
98+
}
99+
100+
_, err := client.Networking().UpdateSecurityList(context.Background(), req)
101+
p := (err == nil)
102+
103+
if (i < int(qpsRead) && !p) || (i >= int(qpsRead) && p) {
104+
t.Errorf("unexpected result from request %d: %v", i, err)
105+
}
106+
}
107+
}
108+
109+
func newClient(rateLimiter RateLimiter) Interface {
110+
return &client{
111+
compute: &mockComputeClient{},
112+
network: &mockVirtualNetworkClient{},
113+
rateLimiter: rateLimiter,
114+
}
115+
}
116+
117+
/* Mock ComputeClient interface implementations */
118+
func (c *mockComputeClient) GetInstance(ctx context.Context, request core.GetInstanceRequest) (response core.GetInstanceResponse, err error) {
119+
return core.GetInstanceResponse{}, nil
120+
}
121+
122+
func (c *mockComputeClient) ListInstances(ctx context.Context, request core.ListInstancesRequest) (response core.ListInstancesResponse, err error) {
123+
return core.ListInstancesResponse{}, nil
124+
}
125+
126+
func (c *mockComputeClient) ListVnicAttachments(ctx context.Context, request core.ListVnicAttachmentsRequest) (response core.ListVnicAttachmentsResponse, err error) {
127+
return core.ListVnicAttachmentsResponse{}, nil
128+
}
129+
130+
/* Mock NetworkClient interface implementations */
131+
func (c *mockVirtualNetworkClient) GetVnic(ctx context.Context, request core.GetVnicRequest) (response core.GetVnicResponse, err error) {
132+
return core.GetVnicResponse{}, nil
133+
}
134+
135+
func (c *mockVirtualNetworkClient) GetSubnet(ctx context.Context, request core.GetSubnetRequest) (response core.GetSubnetResponse, err error) {
136+
return core.GetSubnetResponse{}, nil
137+
}
138+
139+
func (c *mockVirtualNetworkClient) GetSecurityList(ctx context.Context, request core.GetSecurityListRequest) (response core.GetSecurityListResponse, err error) {
140+
return core.GetSecurityListResponse{}, nil
141+
}
142+
143+
func (c *mockVirtualNetworkClient) UpdateSecurityList(ctx context.Context, request core.UpdateSecurityListRequest) (response core.UpdateSecurityListResponse, err error) {
144+
return core.UpdateSecurityListResponse{}, nil
145+
}

0 commit comments

Comments
 (0)