1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "OperationLimiter.h"
18 
19 #include <gtest/gtest-spi.h>
20 #include <netdutils/NetNativeTestBase.h>
21 
22 namespace android {
23 namespace netdutils {
24 
25 class OperationLimiterTest : public NetNativeTestBase {};
26 
TEST_F(OperationLimiterTest,limits)27 TEST_F(OperationLimiterTest, limits) {
28     OperationLimiter<int> limiter(3);
29 
30     EXPECT_TRUE(limiter.start(42));
31     EXPECT_TRUE(limiter.start(42));
32     EXPECT_TRUE(limiter.start(42));
33 
34     // Limit reached... calling any number of times should have no effect.
35     EXPECT_FALSE(limiter.start(42));
36     EXPECT_FALSE(limiter.start(42));
37     EXPECT_FALSE(limiter.start(42));
38 
39     // Finishing a single operations is enough for starting a new one...
40     limiter.finish(42);
41     EXPECT_TRUE(limiter.start(42));
42 
43     // ...but not two!
44     EXPECT_FALSE(limiter.start(42));
45 
46     // Different ids should still have quota...
47     EXPECT_TRUE(limiter.start(666));
48     limiter.finish(666);
49 
50     // Finish all pending operations
51     limiter.finish(42);
52     limiter.finish(42);
53     limiter.finish(42);
54 }
55 
TEST_F(OperationLimiterTest,finishWithoutStart)56 TEST_F(OperationLimiterTest, finishWithoutStart) {
57     OperationLimiter<int> limiter(1);
58 
59     // Will output a LOG(FATAL_WITHOUT_ABORT), but we have no way to probe this.
60     limiter.finish(42);
61 
62     // This will ensure that the finish() above didn't set a negative value.
63     EXPECT_TRUE(limiter.start(42));
64     EXPECT_FALSE(limiter.start(42));
65 }
66 
TEST_F(OperationLimiterTest,destroyWithActiveOperations)67 TEST_F(OperationLimiterTest, destroyWithActiveOperations) {
68     // The death message doesn't seem to be captured on Android.
69     EXPECT_DEBUG_DEATH(
70             {
71                 OperationLimiter<int> limiter(3);
72                 limiter.start(42);
73             },
74             "" /* "active operations */);
75 }
76 
TEST_F(OperationLimiterTest,globalLimits)77 TEST_F(OperationLimiterTest, globalLimits) {
78     OperationLimiter<int> limiter(1);
79 
80     EXPECT_TRUE(limiter.start(42, 2));
81 
82     // Calling with a different key is okay.
83     EXPECT_TRUE(limiter.start(43, 2));
84 
85     // Global limit reached... calling with a different key should have no effect.
86     EXPECT_FALSE(limiter.start(44, 2));
87 
88     // Global limit extended... calling with a different key is available again.
89     EXPECT_TRUE(limiter.start(44, 4));
90 
91     // Per-key limit reached.
92     EXPECT_FALSE(limiter.start(44, 4));
93 
94     // Global limit is still available.
95     EXPECT_TRUE(limiter.start(45, 4));
96 
97     // Global limit reached again.
98     EXPECT_FALSE(limiter.start(46, 4));
99 
100     // Shrink global limit.
101     EXPECT_FALSE(limiter.start(46, 3));
102 
103     // Finish all pending operations
104     for (const auto& key : {42, 43, 44, 45}) {
105         limiter.finish(key);
106     }
107 }
108 
109 }  // namespace netdutils
110 }  // namespace android
111